Java: วิธีกำหนดการเข้ารหัส charset ที่ถูกต้องของสตรีม


140

โดยอ้างถึงเธรดต่อไปนี้: Java App: ไม่สามารถอ่านไฟล์ที่เข้ารหัส iso-8859-1 ได้อย่างถูกต้อง

วิธีที่ดีที่สุดในการกำหนดการเข้ารหัสชุดอักขระของอินพุตสตรีม / ไฟล์โดยทางโปรแกรมคืออะไร

ฉันได้ลองใช้สิ่งต่อไปนี้:

File in =  new File(args[0]);
InputStreamReader r = new InputStreamReader(new FileInputStream(in));
System.out.println(r.getEncoding());

แต่ในไฟล์ที่ฉันรู้ว่าเข้ารหัสด้วย ISO8859_1 โค้ดข้างต้นให้ผลว่า ASCII ซึ่งไม่ถูกต้องและไม่อนุญาตให้ฉันแสดงผลเนื้อหาของไฟล์กลับไปที่คอนโซลอย่างถูกต้อง


11
Eduard นั้นถูกต้อง "คุณไม่สามารถตรวจสอบการเข้ารหัสของสตรีมไบต์โดยพลการ" ข้อเสนออื่น ๆ ทั้งหมดให้วิธี (และห้องสมุด) ในการคาดเดาที่ดีที่สุด แต่ในที่สุดพวกเขาก็ยังเดา
หมดเวลา Nita

9
Reader.getEncodingส่งคืนการเข้ารหัสที่ผู้อ่านตั้งค่าให้ใช้ซึ่งในกรณีของคุณคือการเข้ารหัสเริ่มต้น
Karol S

คำตอบ:


70

ฉันใช้ห้องสมุดนี้คล้ายกับ jchardet เพื่อตรวจจับการเข้ารหัสใน Java: http://code.google.com/p/juniversalchardet/


6
ฉันพบว่าสิ่งนี้ถูกต้องมากขึ้น: jchardet.sourceforge.net (ฉันกำลังทดสอบเอกสารภาษายุโรปตะวันตกที่เข้ารหัสใน ISO 8859-1, windows-1252, utf-8)
Joel

1
Juniversalchardet นี้ใช้งานไม่ได้ มอบเวลาส่วนใหญ่ให้กับ UTF-8 แม้ว่าไฟล์จะได้รับการเข้ารหัส 100% windows-1212
สมอง

1
juniversalchardet ได้เข้าร่วม GitHubแล้ว
deamon

ไม่พบ windows-1250 ในยุโรปตะวันออก
Bernhard Döbler

ฉันลองใช้โค้ดต่อไปนี้เพื่อตรวจหาไฟล์จาก " cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt " แต่ได้รับการตรวจพบชุดอักขระ UniversalDetector ud = new UniversalDetector (null); byte [] bytes = FileUtils.readFileToByteArray (ไฟล์ใหม่ (ไฟล์)); ud.handleData (ไบต์, 0, bytes.length); ud.dataEnd (); detectCharset = ud.getDetectedCharset ();
Rohit Verma

105

คุณไม่สามารถกำหนดการเข้ารหัสของสตรีมไบต์ที่กำหนดเองได้ นี่คือธรรมชาติของการเข้ารหัส การเข้ารหัสหมายถึงการจับคู่ระหว่างค่าไบต์และการแทนค่า ดังนั้นการเข้ารหัส "อาจ" เป็นสิ่งที่ถูกต้อง

getEncoding ()วิธีการจะกลับมาเข้ารหัสที่ถูกจัดตั้งขึ้น (อ่านJavaDoc ) สำหรับสตรีม มันจะไม่เดาการเข้ารหัสสำหรับคุณ

สตรีมบางตัวบอกคุณว่าการเข้ารหัสที่ใช้ในการสร้าง: XML, HTML แต่ไม่ใช่สตรีมไบต์ที่กำหนดเอง

อย่างไรก็ตามคุณสามารถลองเดาการเข้ารหัสด้วยตัวคุณเองถ้าคุณต้องการ ทุกภาษามีความถี่ร่วมกันสำหรับถ่านทุกตัว ในภาษาอังกฤษ char e ปรากฏบ่อยมาก แต่êจะไม่ค่อยปรากฏมากนัก ในสตรีม ISO-8859-1 โดยปกติจะไม่มีตัวอักษร 0x00 ตัว แต่กระแส UTF-16 มีจำนวนมาก

หรือ: คุณสามารถถามผู้ใช้ ฉันได้เห็นแอปพลิเคชั่นที่นำเสนอตัวอย่างของไฟล์ในการเข้ารหัสที่แตกต่างกันและขอให้คุณเลือก "แก้ไข"


18
นี่ไม่ได้ตอบคำถามจริงๆ สหกรณ์ควรอาจจะใช้docs.codehaus.org/display/GUESSENC/Homeหรือicu-project.org/apiref/icu4j/com/ibm/icu/text/...หรือjchardet.sourceforge.net
Christoffer Hammarström

23
ดังนั้นตัวแก้ไข notepad ++ ของฉันจะรู้วิธีเปิดไฟล์และแสดงอักขระที่ถูกต้องได้อย่างไร
mmm

12
@Hamidam เป็นโชคที่แสดงให้คุณเห็นถึงตัวละครที่ถูกต้อง เมื่อเดาผิด (และบ่อยครั้ง) จะมีตัวเลือก (เมนู >> การเข้ารหัส) ที่ให้คุณเปลี่ยนการเข้ารหัส
Pacerier

15
@Eduard: "ดังนั้นทุกการเข้ารหัส" อาจ "ถูกต้อง" ไม่ถูกต้องนัก การเข้ารหัสข้อความจำนวนมากมีหลายรูปแบบที่ไม่ถูกต้องซึ่งเป็นธงที่ข้อความนั้นอาจไม่ได้เข้ารหัสนั้น ในความเป็นจริงให้สองไบต์แรกของไฟล์เพียง 38% ของการรวมกันเป็น UTF8 ที่ถูกต้อง อัตราเดิมพันของ 5 codepoints แรกที่ถูกต้อง UTF8 โดยบังเอิญนั้นน้อยกว่า. 77% ในทำนองเดียวกัน UTF16BE และ LE มักจะระบุได้อย่างง่ายดายโดยจำนวนศูนย์ไบต์ขนาดใหญ่และที่พวกเขาอยู่
Mooing Duck

38

ลองดูที่นี่: http://site.icu-project.org/ (icu4j) พวกเขามีห้องสมุดสำหรับการตรวจจับชุดอักขระจาก IOStream อาจเป็นเรื่องง่ายเช่นนี้:

BufferedInputStream bis = new BufferedInputStream(input);
CharsetDetector cd = new CharsetDetector();
cd.setText(bis);
CharsetMatch cm = cd.detect();

if (cm != null) {
   reader = cm.getReader();
   charset = cm.getName();
}else {
   throw new UnsupportedCharsetException()
}

2
ฉันลองแล้ว แต่มันล้มเหลวอย่างมาก: ฉันสร้างไฟล์ข้อความ 2 ไฟล์ใน eclipse ซึ่งมีทั้ง "öäüß" หนึ่งชุดเป็นการเข้ารหัส iso และหนึ่งถึง utf8 - ทั้งคู่ถูกตรวจพบเป็น utf8! ดังนั้นฉันลองไฟล์ที่ปลอดภัยที่ไหนสักแห่งใน hd ของฉัน (windows) - อันนี้ถูกตรวจพบอย่างถูกต้อง ("windows-1252") จากนั้นฉันสร้างไฟล์ใหม่สองไฟล์บน hd หนึ่งไฟล์หนึ่งแก้ไขด้วยเอดิเตอร์อีกไฟล์หนึ่งด้วย notepad ++ ในทั้งสองกรณีตรวจพบ "Big5" (ภาษาจีน)!
dermoritz

2
แก้ไข: ตกลงฉันควรตรวจสอบ cm.getConfidence () - ด้วยความมั่นใจ "äöüß" สั้น ๆ ของฉันคือ 10 ดังนั้นฉันต้องตัดสินใจว่าความมั่นใจเป็นสิ่งที่ดีพอ - แต่นั่นก็โอเคอย่างแน่นอนสำหรับความพยายามนี้ (การตรวจสอบชุดอักขระ)
dermoritz

1
ลิงก์โดยตรงไปยังรหัสตัวอย่าง: userguide.icu-project.org/conversion/detection
james.garriss

27

นี่คือรายการโปรดของฉัน:

TikaEncodingDetector

การอ้างอิง:

<dependency>
  <groupId>org.apache.any23</groupId>
  <artifactId>apache-any23-encoding</artifactId>
  <version>1.1</version>
</dependency>

ตัวอย่าง:

public static Charset guessCharset(InputStream is) throws IOException {
  return Charset.forName(new TikaEncodingDetector().guessEncoding(is));    
}

GuessEncoding

การอ้างอิง:

<dependency>
  <groupId>org.codehaus.guessencoding</groupId>
  <artifactId>guessencoding</artifactId>
  <version>1.4</version>
  <type>jar</type>
</dependency>

ตัวอย่าง:

  public static Charset guessCharset2(File file) throws IOException {
    return CharsetToolkit.guessEncoding(file, 4096, StandardCharsets.UTF_8);
  }

2
หมายเหตุ: TikaEncodingDetector 1.1เป็นจริงเสื้อคลุมบาง ๆ รอบICU4J 3.4 CharsetDectectorชั้น
เตฟาน

น่าเสียดายที่ libs ทั้งสองไม่ทำงาน ในกรณีหนึ่งจะระบุไฟล์ UTF-8 พร้อม Umlaute เยอรมันเป็น ISO-8859-1 และ US-ASCII
สมอง

1
@Brain: ไฟล์ทดสอบของคุณเป็นรูปแบบ UTF-8 จริงหรือไม่และประกอบด้วย BOM ( en.wikipedia.org/wiki/Byte_order_mark ) หรือไม่
Benny Neugebauer

@BennyNeugebauer ไฟล์นี้เป็น UTF-8 โดยไม่มี BOM ฉันตรวจสอบด้วย Notepad ++ ด้วยการเปลี่ยนการเข้ารหัสและยืนยันว่า "Umlaute" ยังคงมองเห็นได้
สมอง

13

คุณสามารถตรวจสอบความถูกต้องของไฟล์สำหรับชุดอักขระเฉพาะได้อย่างแน่นอนโดยการถอดรหัสด้วยCharsetDecoderและดูข้อผิดพลาด "malformed-input" หรือ "unmappable-character" error แน่นอนสิ่งนี้จะบอกคุณว่าชุดอักขระนั้นผิดหรือเปล่า มันไม่ได้บอกคุณว่ามันถูกต้องหรือไม่ เพื่อที่คุณจะต้องมีพื้นฐานของการเปรียบเทียบเพื่อประเมินผลการถอดรหัสเช่นคุณรู้ล่วงหน้าหรือไม่ว่าตัวละครนั้นถูก จำกัด ไว้ที่เซตย่อยบางส่วนหรือไม่ บรรทัดล่างคือการตรวจจับชุดอักขระนั้นเป็นการคาดเดาโดยไม่มีการรับประกันใด ๆ


12

ห้องสมุดไหนที่จะใช้?

จากการเขียนนี้พวกเขาเป็นห้องสมุดสามแห่งที่ปรากฏ:

ฉันไม่ได้รวมApache Any23เพราะใช้ ICU4j 3.4 ภายใต้ประทุน

จะบอกได้อย่างไรว่าตัวใดตรวจจับชุดอักขระที่ถูกต้อง (หรือใกล้เคียงที่สุด)

เป็นไปไม่ได้ที่จะรับรองชุดอักขระที่ตรวจพบโดยแต่ละไลบรารีด้านบน อย่างไรก็ตามเป็นไปได้ที่จะขอให้พวกเขากลับมาและให้คะแนนการตอบกลับ

จะให้คะแนนการตอบกลับอย่างไร

การตอบสนองแต่ละครั้งสามารถกำหนดได้หนึ่งจุด ยิ่งมีการตอบสนองมากเท่าใดยิ่งมั่นใจชุดอักขระที่ตรวจพบก็จะยิ่งมากขึ้นเท่านั้น นี่เป็นวิธีการให้คะแนนแบบง่าย ๆ คุณสามารถทำอย่างละเอียดอื่น ๆ

มีรหัสตัวอย่างหรือไม่?

นี่คือข้อมูลโค้ดแบบสมบูรณ์ที่ใช้กลยุทธ์ที่อธิบายไว้ในบรรทัดก่อนหน้า

public static String guessEncoding(InputStream input) throws IOException {
    // Load input data
    long count = 0;
    int n = 0, EOF = -1;
    byte[] buffer = new byte[4096];
    ByteArrayOutputStream output = new ByteArrayOutputStream();

    while ((EOF != (n = input.read(buffer))) && (count <= Integer.MAX_VALUE)) {
        output.write(buffer, 0, n);
        count += n;
    }
    
    if (count > Integer.MAX_VALUE) {
        throw new RuntimeException("Inputstream too large.");
    }

    byte[] data = output.toByteArray();

    // Detect encoding
    Map<String, int[]> encodingsScores = new HashMap<>();

    // * GuessEncoding
    updateEncodingsScores(encodingsScores, new CharsetToolkit(data).guessEncoding().displayName());

    // * ICU4j
    CharsetDetector charsetDetector = new CharsetDetector();
    charsetDetector.setText(data);
    charsetDetector.enableInputFilter(true);
    CharsetMatch cm = charsetDetector.detect();
    if (cm != null) {
        updateEncodingsScores(encodingsScores, cm.getName());
    }

    // * juniversalchardset
    UniversalDetector universalDetector = new UniversalDetector(null);
    universalDetector.handleData(data, 0, data.length);
    universalDetector.dataEnd();
    String encodingName = universalDetector.getDetectedCharset();
    if (encodingName != null) {
        updateEncodingsScores(encodingsScores, encodingName);
    }

    // Find winning encoding
    Map.Entry<String, int[]> maxEntry = null;
    for (Map.Entry<String, int[]> e : encodingsScores.entrySet()) {
        if (maxEntry == null || (e.getValue()[0] > maxEntry.getValue()[0])) {
            maxEntry = e;
        }
    }

    String winningEncoding = maxEntry.getKey();
    //dumpEncodingsScores(encodingsScores);
    return winningEncoding;
}

private static void updateEncodingsScores(Map<String, int[]> encodingsScores, String encoding) {
    String encodingName = encoding.toLowerCase();
    int[] encodingScore = encodingsScores.get(encodingName);

    if (encodingScore == null) {
        encodingsScores.put(encodingName, new int[] { 1 });
    } else {
        encodingScore[0]++;
    }
}    

private static void dumpEncodingsScores(Map<String, int[]> encodingsScores) {
    System.out.println(toString(encodingsScores));
}

private static String toString(Map<String, int[]> encodingsScores) {
    String GLUE = ", ";
    StringBuilder sb = new StringBuilder();

    for (Map.Entry<String, int[]> e : encodingsScores.entrySet()) {
        sb.append(e.getKey() + ":" + e.getValue()[0] + GLUE);
    }
    int len = sb.length();
    sb.delete(len - GLUE.length(), len);

    return "{ " + sb.toString() + " }";
}

การปรับปรุง:guessEncodingวิธีการอ่าน InputStream ทั้งหมด สำหรับอินพุตขนาดใหญ่นี่อาจเป็นเรื่องกังวล ไลบรารีทั้งหมดเหล่านี้จะอ่านอินพุตทั้งหมด นี่จะเป็นการใช้เวลานานมากในการตรวจจับชุดอักขระ

เป็นไปได้ที่จะ จำกัด การโหลดข้อมูลเริ่มต้นเพียงไม่กี่ไบต์และทำการตรวจจับชุดอักขระบนสองสามไบต์เท่านั้น


8

libs ด้านบนเป็นตัวตรวจจับ BOM อย่างง่ายซึ่งแน่นอนว่าจะทำงานเฉพาะในกรณีที่มี BOM ในตอนเริ่มต้นของไฟล์ ลองดูที่http://jchardet.sourceforge.net/ซึ่งทำการสแกนข้อความ


18
ที่ปลาย แต่ไม่มี "เหนือ" ในเว็บไซต์นี้ - พิจารณาการระบุไลบรารีที่คุณกำลังอ้างอิง
McDowell

6

เท่าที่ฉันรู้ไม่มีห้องสมุดทั่วไปในบริบทนี้ที่จะเหมาะกับปัญหาทุกประเภท ดังนั้นสำหรับแต่ละปัญหาคุณควรทดสอบไลบรารีที่มีอยู่และเลือกไลบรารีที่ดีที่สุดที่ตรงกับข้อ จำกัด ของปัญหา แต่บ่อยครั้งที่มันไม่เหมาะสม ในกรณีเหล่านี้คุณสามารถเขียนเครื่องตรวจจับการเข้ารหัสของคุณเอง! ตามที่ฉันได้เขียน ...

ฉันเขียนเครื่องมือ meta java สำหรับตรวจจับการเข้ารหัส charset ของเว็บเพจ HTML โดยใช้ IBM ICU4j และ Mozilla JCharDet เป็นส่วนประกอบในตัว ที่นี่คุณสามารถค้นหาเครื่องมือของฉันโปรดอ่านส่วน README ก่อนสิ่งอื่นใด นอกจากนี้คุณยังสามารถหาแนวคิดพื้นฐานบางส่วนของปัญหานี้ในของฉันกระดาษและในการอ้างอิง

ซอลเบลโลว์ฉันให้ความเห็นที่เป็นประโยชน์ซึ่งฉันได้พบในงานของฉัน:

  • การตรวจจับชุดอักขระไม่ใช่กระบวนการที่เข้าใจผิดได้เพราะมันใช้ข้อมูลสถิติเป็นหลักและสิ่งที่เกิดขึ้นจริงคือการคาดเดาไม่ได้ตรวจจับ
  • icu4j เป็นเครื่องมือหลักในบริบทนี้โดย IBM, imho
  • ทั้ง TikaEncodingDetector และ Lucene-ICU4j กำลังใช้ icu4j และความแม่นยำของมันก็ไม่ได้มีความแตกต่างที่มีความหมายซึ่ง icu4j ในการทดสอบของฉัน (ที่% 1 ตามที่ฉันจำได้)
  • icu4j นั้นกว้างกว่า jchardet, icu4j นั้นค่อนข้างเอนเอียงไปยังการเข้ารหัสตระกูล IBM ในขณะที่ jchardet นั้นมีอคติอย่างมากกับ utf-8
  • เนื่องจากมีการใช้ UTF-8 อย่างแพร่หลายใน HTML-world jchardet เป็นตัวเลือกที่ดีกว่าโดยรวม icu4j แต่ไม่ใช่ตัวเลือกที่ดีที่สุด!
  • icu4j นั้นยอดเยี่ยมสำหรับการเข้ารหัสเฉพาะในเอเชียตะวันออกเช่น EUC-KR, EUC-JP, SHIFT_JIS, BIG5 และการเข้ารหัสตระกูล GB
  • ทั้ง icu4j และ jchardet เป็น debacle ในการจัดการกับหน้า HTML ที่มีการเข้ารหัส Windows-1251 และ Windows-1256 Windows-1251 aka cp1251 ใช้กันอย่างแพร่หลายสำหรับภาษาที่ใช้ภาษาซิริลลิเช่นรัสเซียและ Windows-1256 aka cp1256 ใช้กันอย่างแพร่หลายสำหรับภาษาอาหรับ
  • เครื่องมือตรวจจับการเข้ารหัสเกือบทั้งหมดใช้วิธีการทางสถิติดังนั้นความแม่นยำของเอาต์พุตจึงขึ้นอยู่กับขนาดและเนื้อหาของอินพุต
  • การเข้ารหัสบางอย่างนั้นเหมือนกันเพียงแค่มีความแตกต่างบางส่วนดังนั้นในบางกรณีการเข้ารหัสที่เดาหรือตรวจพบอาจเป็นเท็จ แต่ในขณะเดียวกันก็เป็นจริง! เกี่ยวกับ Windows-1252 และ ISO-8859-1 (อ้างถึงย่อหน้าสุดท้ายภายใต้หัวข้อ 5.2 ในกระดาษของฉัน)

5

ฉันพบห้องสมุดบุคคลที่สามที่ดีซึ่งสามารถตรวจจับการเข้ารหัสที่เกิดขึ้นจริง: http://glaforge.free.fr/wiki/index.php?wiki=GuessEncoding

ฉันไม่ได้ทดสอบอย่างกว้างขวาง แต่ดูเหมือนว่าจะใช้งานได้


ลิงก์ไปยังเว็บไซต์โครงการ "GuessEncoding" คือ: xircles.codehaus.org/p/guessencoding
Benny Neugebauer

5

หากคุณใช้ ICU4J ( http://icu-project.org/apiref/icu4j/ )

นี่คือรหัสของฉัน:

String charset = "ISO-8859-1"; //Default chartset, put whatever you want

byte[] fileContent = null;
FileInputStream fin = null;

//create FileInputStream object
fin = new FileInputStream(file.getPath());

/*
 * Create byte array large enough to hold the content of the file.
 * Use File.length to determine size of the file in bytes.
 */
fileContent = new byte[(int) file.length()];

/*
 * To read content of the file in byte array, use
 * int read(byte[] byteArray) method of java FileInputStream class.
 *
 */
fin.read(fileContent);

byte[] data =  fileContent;

CharsetDetector detector = new CharsetDetector();
detector.setText(data);

CharsetMatch cm = detector.detect();

if (cm != null) {
    int confidence = cm.getConfidence();
    System.out.println("Encoding: " + cm.getName() + " - Confidence: " + confidence + "%");
    //Here you have the encode name and the confidence
    //In my case if the confidence is > 50 I return the encode, else I return the default value
    if (confidence > 50) {
        charset = cm.getName();
    }
}

จำไว้ว่าให้นำทุกสิ่งที่คุณต้องการมาลองใช้

ฉันหวังว่าสิ่งนี้จะได้ผลสำหรับคุณ


IMO คำตอบนี้สมบูรณ์แบบ หากคุณต้องการที่จะใช้ ICU4j ลองนี้แทน: stackoverflow.com/a/4013565/363573
เตฟาน

4

หากคุณไม่ทราบว่าการเข้ารหัสของข้อมูลของคุณก็เป็นได้เพื่อง่ายต่อการตรวจสอบ แต่คุณสามารถพยายามที่จะใช้ห้องสมุดที่จะคาดเดาว่ามัน นอกจากนี้ยังมีคำถามที่คล้ายกัน


2

สำหรับไฟล์ ISO8859_1 ไม่มีวิธีที่ง่ายในการแยกความแตกต่างจาก ASCII สำหรับไฟล์ Unicode แต่โดยทั่วไปจะสามารถตรวจจับสิ่งนี้ตามสองสามไบต์แรกของไฟล์

ไฟล์ UTF-8 และ UTF-16 จะมีByte Order Mark (BOM) ที่จุดเริ่มต้นของไฟล์ BOM เป็นพื้นที่ไม่ทำลายความกว้างเป็นศูนย์

น่าเสียดายด้วยเหตุผลทางประวัติศาสตร์ Java ไม่พบสิ่งนี้โดยอัตโนมัติ โปรแกรมเช่น Notepad จะตรวจสอบ BOM และใช้การเข้ารหัสที่เหมาะสม ใช้ unix หรือ Cygwin คุณสามารถตรวจสอบ BOM ด้วยคำสั่ง file ตัวอย่างเช่น:

$ file sample2.sql 
sample2.sql: Unicode text, UTF-16, big-endian

สำหรับ Java ฉันขอแนะนำให้คุณตรวจสอบรหัสนี้ซึ่งจะตรวจจับรูปแบบไฟล์ทั่วไปและเลือกการเข้ารหัสที่ถูกต้อง: วิธีอ่านไฟล์และระบุการเข้ารหัสที่ถูกต้องโดยอัตโนมัติ


15
ไม่ใช่ไฟล์ UTF-8 หรือ UTF-16 ทั้งหมดที่มี BOM เนื่องจากไม่จำเป็นและไฟล์ UTF-8 BOM จะหมดกำลังใจ
Christoffer Hammarström

1

ทางเลือกในการ TikaEncodingDetector คือการใช้Tika AutoDetectReader

Charset charset = new AutoDetectReader(new FileInputStream(file)).getCharset();

Tike AutoDetectReader ใช้ EncodingDetector ที่โหลดด้วย ServiceLoader คุณใช้การเข้ารหัสแบบใด
เตฟาน

-1

ใน Java ธรรมดา:

final String[] encodings = { "US-ASCII", "ISO-8859-1", "UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16" };

List<String> lines;

for (String encoding : encodings) {
    try {
        lines = Files.readAllLines(path, Charset.forName(encoding));
        for (String line : lines) {
            // do something...
        }
        break;
    } catch (IOException ioe) {
        System.out.println(encoding + " failed, trying next.");
    }
}

วิธีนี้จะลองการเข้ารหัสทีละตัวจนกว่าเราจะได้ผลหรือเราหมดมันไป (BTW รายการเข้ารหัสของฉันมีเฉพาะรายการเหล่านั้นเพราะเป็นชุดการใช้งานที่ต้องการในทุกแพลตฟอร์ม Java https://docs.oracle.com/javase/9/docs/api/java/nio/charset/Charset.html )


แต่ ISO-8859-1 (ท่ามกลางคนอื่น ๆ ที่คุณไม่ได้ระบุไว้) จะประสบความสำเร็จเสมอ และแน่นอนว่านี่เป็นเพียงการคาดเดาซึ่งไม่สามารถกู้คืนข้อมูลเมตาที่หายไปซึ่งจำเป็นต่อการสื่อสารไฟล์ข้อความ
Tom Blodget

สวัสดี @TomBlodget คุณแนะนำว่าการเข้ารหัสควรแตกต่างกันหรือไม่?
Andres

3
ฉันบอกว่าหลายคนจะ "ทำงาน" แต่เพียงคนเดียวคือ "ถูกต้อง" และคุณไม่จำเป็นต้องทดสอบ ISO-8859-1 เพราะมันจะ "ทำงาน" เสมอ
Tom Blodget

-12

คุณสามารถเลือกชุดถ่านที่เหมาะสมในตัวสร้างได้หรือไม่ :

new InputStreamReader(new FileInputStream(in), "ISO8859_1");

8
จุดที่นี่คือเพื่อดูว่าสามารถกำหนดชุดอักขระแบบมีโปรแกรมหรือไม่
Joel

1
ไม่มันจะไม่เดาให้คุณ คุณต้องจัดหามัน
เควิน

1
อาจจะมีวิธีการแก้ปัญหาตามที่แนะนำโดยบางส่วนของคำตอบที่นี่stackoverflow.com/questions/457655/java-charset-and-windows/...
โจเอล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.