常見於:資料庫編碼設定錯誤、檔案讀取編碼不符、第三方介面回傳編碼未標註。亂碼本質是錯誤編碼導致位元組序列被誤解碼,若原始內容為 UTF-8 卻用 GBK 讀取,會產生「字元膨脹」(一個中文字變兩三個亂碼字)。反推原理:**正確解碼後的字串長度通常最短**(資訊熵最低)。
ISO-8859-1、GBK、UTF-8、Big5 等。sourceCharset → targetCharset 組合。package com.hongyuan.test;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
public class CharsetDetector {
private static final String[] CHARSETS = {
"ISO-8859-1", "GBK", "UTF-8", "Big5", "UTF-16LE", "UTF-16BE"
};
public static Result detect(String garbled) {
int minLen = Integer.MAX_VALUE;
String best = null, src = null, tgt = null;
for (String s : CHARSETS) {
byte[] bytes;
try { bytes = garbled.getBytes(s); }
catch (UnsupportedEncodingException e) { continue; }
for (String t : CHARSETS) {
String decoded;
try { decoded = new String(bytes, t); }
catch (UnsupportedEncodingException e) { continue; }
if (decoded.length() < minLen) {
minLen = decoded.length();
best = decoded; src = s; tgt = t;
}
}
}
return new Result(src, tgt, best, minLen);
}
public static class Result {
public final String sourceCharset, targetCharset, content;
public final int length;
Result(String s, String t, String c, int l) { sourceCharset=s; targetCharset=t; content=c; length=l; }
@Override public String toString() {
return String.format("%s → %s (len=%d): %s", sourceCharset, targetCharset, length, content);
}
}
public static void main(String[] args) {
String garbled = "寰蔣鐧懼害鍏辨帹Windows XP鑱斿悎闃叉姢瑙e喅鏂規"; // 百度首頁 UTF-8 被 GBK 讀取
System.out.println(detect(garbled));
// 輸出範例:GBK → UTF-8 (len=42): 百度一下,你就知道 Windows XP 完美清爽版官方下載
}
}
| 可行情況 | 失效情況 |
|---|---|
| 單次編碼錯誤(如 UTF-8→GBK) | 多重編碼錯誤(UTF-8→GBK→ISO-8859-1) |
| 亂碼文本完整無遺漏 | 亂碼含不可見控制字元導致位元組缺失 |
| 原始字集較大、錯誤字集較小 | 原始字集較小、錯誤字集較大(資訊已截斷) |
| 字元分布具備統計特徵 | 極短字串(<10字)或全 ASCII 字元(無統計差異) |
juniversalchardet 作為輔助驗證。十幾行核心代碼解決 80% 亂碼救援需求,建議專案內建為 CharsetDetector 工具類,配合單元測試覆蓋常見編碼組合。