Java 內部使用 UTF-16,但早期 Web 容器(Tomcat 5/6、Resin)預設用 ISO-8859-1 解碼 HTTP 參數,導致中文變成「???」或亂碼。核心修正原理:取得錯誤解碼後的 String → 用錯誤編碼 getBytes() 還原原始位元組 → 用正確編碼 new String(bytes, charset) 重組。
| 場景 | 錯誤編碼 | 正確編碼 | 修正代碼 |
|---|---|---|---|
| GET 參數 | ISO-8859-1 | UTF-8/GBK | new String(param.getBytes("ISO-8859-1"), "UTF-8") |
| 資料庫讀出 | ISO-8859-1 | GBK/UTF-8 | new String(rs.getString(i).getBytes("ISO-8859-1"), "GBK") |
| 檔案讀取 | 平台預設 | UTF-8 | new String(Files.readAllBytes(path), "UTF-8") |
public final class CharsetFixer {
private CharsetFixer() {}
/**
* 修正因 ISO-8859-1 錯誤解碼產生的中文字串
* @param garbled 亂碼字串
* @param targetCharset 目標正確編碼(UTF-8、GBK、Big5 等)
* @return 修正後字串,若輸入為 null 回傳空字串
*/
public static String fixISO88591(String garbled, String targetCharset) {
if (garbled == null) return "";
try {
byte[] bytes = garbled.getBytes("ISO-8859-1");
return new String(bytes, targetCharset);
} catch (UnsupportedEncodingException e) {
// 理論不會發生,JDK 必備編碼
return garbled;
}
}
/** 預設修正為 UTF-8 */
public static String fixToUTF8(String garbled) {
return fixISO88591(garbled, "UTF-8");
}
/** 預設修正為 GBK */
public static String fixToGBK(String garbled) {
return fixISO88591(garbled, "GBK");
}
}
<Connector URIEncoding="UTF-8" /><%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");?characterEncoding=utf8&useUnicode=true;Oracle 設定 NLS_LANG。// 使用 StandardCharsets 避免字串拼寫錯誤
import java.nio.charset.StandardCharsets;
String fixed = new String(garbled.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
徹底解決中文亂碼的關鍵在於統一全鏈路編碼,工具類僅作為歷史資料搬遷或第三方介面無法修改時的補救手段。