Java 程式開發中,中文亂碼是令開發者頭痛的常見問題。Java 內部採用 Unicode (UTF-16) 編碼,而中文環境常用 Big5、GB2312/GBK、UTF-8 等編碼。編碼不匹配會導致資料庫儲存、檔案讀寫、網頁顯示、Console 輸出等環節產生亂碼。本文從編碼基礎出發,系統分析 Java 中文處理全鏈路,提供實戰解決方案。
| 編碼 | 說明 | 適用範圍 |
|---|---|---|
| ASCII | 1 Byte,0x00-0x7F | 英文字元 |
| Big5 | 2 Bytes,高位元為 1 | 繁體中文(台灣、香港) |
| GB2312/GBK | 2 Bytes,高位元為 1 | 簡體中文(大陸、新加坡) |
| Unicode (UTF-16) | 2-4 Bytes 固定長度 | Java 內部字元表示 |
| UTF-8 | 1-4 Bytes 變長 | 網頁、檔案儲存、傳輸標準 |
Java String 內部為 UTF-16。"蘋果".length() == 2(字元數),但 getBytes("UTF-8").length == 6(位元組數)。
javac -encoding UTF-8 指定原始檔編碼,避免 Linux (預設 ISO-8859-1) 編譯亂碼。System.getProperty("file.encoding") 影響預設編碼,Windows 通常為 Cp1252/GBK,Linux 為 UTF-8。InputStreamReader/OutputStreamWriter 必須顯式指定編碼,切勿依賴預設值。characterEncoding=UTF-8,連線池層面統一設定。// 建議所有 .java 檔案儲存為 UTF-8
javac -encoding UTF-8 MyClass.java
// 讀取 GBK 編碼檔案
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream("gbk.txt"), "GBK"))) {
String line;
while ((line = br.readLine()) != null) { /* 處理 */ }
}
// 寫入 UTF-8 檔案
try (BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("utf8.txt"), "UTF-8"))) {
bw.write("內容");
}
// JSP 頁面指令
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
// Servlet 設定
request.setCharacterEncoding("UTF-8"); // 必須在 getParameter() 前呼叫
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
// MySQL 範例
String url = "jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Taipei";
// PostgreSQL
String url = "jdbc:postgresql://localhost:5432/db?charSet=UTF-8";
// Oracle (JDBC 12.1+ 自動處理,舊版需 orai18n.jar)
Properties props = new Properties();
props.setProperty("user", "usr");
props.setProperty("password", "pwd");
props.setProperty("defaultNChar", "true"); // 國字集支援
/**
* 修復 ISO-8859-1 錯誤解碼的中文參數
* 適用:Tomcat 預設 ISO-8859-1 解碼 GET 參數,實際為 UTF-8/GBK
*/
public static String fixEncoding(String param, String actualEncoding) {
if (param == null) return null;
try {
return new String(param.getBytes("ISO-8859-1"), actualEncoding);
} catch (UnsupportedEncodingException e) {
return param; // 回退原值
}
}
// 使用範例
String fixed = fixEncoding(request.getParameter("keyword"), "UTF-8");
javac / IDE 建置編碼設定正確?file.encoding 系統屬性是否符合預期?Content-Type 一致?fixEncoding)。utf8mb4 (MySQL) 或 NVARCHAR (SQL Server/Oracle)。中文亂碼本質是「編碼不一致」。現代 Java 開發應建立「UTF-8 全鏈路」標準:原始碼、編譯、運行時、I/O、資料庫、Web 輸出、前端顯示全環節統一 UTF-8。舊系統可透過邊界轉換器漸進式遷移。掌握 Charset、Reader/Writer、JDBC 連線參數、Servlet 過濾器編碼設定等核心 API,即可從根本解決亂碼困擾。