文本文件開頭 3 個位元組可能包含編碼標識(BOM)。讀取前 3 字節,判斷其值即可識別編碼。中文環境下常見 GBK(Windows 預設)與 UTF-8 兩種。
UTF-8 檔案前 3 字節固定為:-17, -69, -65(即十六進制 EF BB BF)。
File file = new File(path);
InputStream is = new FileInputStream(file);
byte[] b = new byte[3];
is.read(b);
is.close();
if (b[0] == -17 && b[1] == -69 && b[2] == -65) {
System.out.println("UTF-8 編碼");
} else {
System.out.println("可能是 GBK 或其他編碼");
}
適用於編碼不可控場景(用戶上傳 HTML/XML 等)。cpdetector 僅 500KB,基於統計學原理,支援多種探測器鏈。
public static String getFileEncode(String path) {
CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
// HTML/XML 解析探測器
detector.add(new ParsingDetector(false));
// Mozilla JChardet 封裝,覆蓋大多數情況
detector.add(JChardetFacade.getInstance());
// ASCII 與 Unicode 家族探測器
detector.add(ASCIIDetector.getInstance());
detector.add(UnicodeDetector.getInstance());
Charset charset = detector.detectCodepage(new File(path).toURI().toURL());
return charset != null ? charset.name() : null;
}
⚠️ cpdetector 基於統計學,不保證 100% 正確。
charset = detector.detectCodepage(InputStream in, int length);
指定檢測字節數,字節越多越準確但越慢,不可超過流長度。
Properties.load() 使用 ISO-8859-1 讀取,導致中文亂碼。解決方案:
String value = props.getProperty("key");
String realValue = new String(value.getBytes("ISO-8859-1"), 实际编码);
實際編碼即可用上述方法自動檢測獲得。
// 獲取 JVM 支援的所有編碼
Charset.availableCharsets().keySet();
// 獲取系統預設編碼
Charset.defaultCharset();
掌握編碼檢測,告別亂碼困擾。