亂碼是軟體開發中普遍且棘手的問題。本文從編碼本質出發,系統梳理亂碼產生的兩大核心原因,並提供針對性解決方案。
記事本不儲存編碼資訊,純位元組存取,「寫入什麼即顯示什麼」。這也是為何它常被作為編碼診斷的基準工具。
Excel 預設使用系統 ANSI 編碼(中文環境為 GBK/CP936)。若程式以 UTF-8 寫入,Excel 以 ANSI 讀取,必然產生亂碼。
伺服器回傳 UTF-8 頁面,但頁面未宣告 <meta charset="UTF-8">,瀏覽器回退預設編碼(如 GBK)解碼 → 亂碼。
解決:HTTP 標頭 Content-Type: text/html; charset=UTF-8 + 頁面 meta 標籤雙重保障。
瀏覽器下載時依預設編碼(GB 系列)解析 Content-Disposition 標頭中的檔名,而後端常以 UTF-8 編碼。
解決:檔名手動編碼為 ISO-8859-1 或 RFC 5987 格式:
// Spring MVC 範例
String fileName = URLEncoder.encode("中文檔名.csv", "UTF-8").replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
Excel 預設以 ANSI 開啟 CSV,但支援 UTF-8 **帶 BOM (Byte Order Mark)** 自動識別。
解決:寫入 UTF-8 BOM 標記 (EF BB BF):
OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=test.csv");
// 寫入 BOM
osw.write(new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF});
osw.write(csvContent);
osw.flush();
-Dfile.encoding=UTF-8)、IDE、建構工具getBytes()、new String(bytes)、IO 流建構必須顯式傳編碼參數useUnicode=true&characterEncoding=UTF-8contentType、Form accept-charsetpublic final class CharsetUtil {
public static String convert(String input, String fromCharset, String toCharset) {
try {
return new String(input.getBytes(fromCharset), toCharset);
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
}
}