亂碼本質是**「編碼宣告與實際位元組序列不匹配」**。涉及 HTTP 標頭、HTML Meta、資料庫連線、程式語言內部編碼、瀏覽器解析順序五大層面。本文建立「編碼一致性鏈路」檢查清單,覆蓋 Apache、PHP、Java (JSP/Servlet)、CGI (Perl) 四大主流棧,提供標準配置模板與避坑指南。
現代應用**強制推薦全鏈路 UTF-8**:資料庫、連線、伺服器、程式、頁面、瀏覽器。僅在極舊系統維護時才考慮 GBK/Big5。
# 關閉預設字元集宣告,讓頁面 Meta/HTTP 標頭決定
# AddDefaultCharset ISO-8859-1
AddDefaultCharset Off
# 或明確宣告 UTF-8 (若確定全站 UTF-8)
# AddDefaultCharset UTF-8
# 輸出過濾器確保 Content-Type 標頭攜帶 charset
AddType 'text/html; charset=UTF-8' .html .htm .php .jsp
AddCharset UTF-8 .html .htm .php .jsp .css .js .xml .json
# mod_deflate/mod_gzip 壓縮不改變編碼,確保不雙重壓縮
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>...</title>
...
</head>
關鍵: IE 解析順序為「HTML Meta → HTTP 標頭」;Firefox/Chrome 反之。Meta 必須在**任何非 ASCII 字元 (含 `
; 內部編碼
default_charset = "UTF-8"
; 輸入/輸出/內部編碼統一 (PHP 5.6+)
input_encoding = "UTF-8"
output_encoding = "UTF-8"
internal_encoding = "UTF-8"
; 多位元組字串函數預設編碼
mbstring.language = Neutral
mbstring.internal_encoding = UTF-8
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.encoding_translation = Off
mbstring.detect_order = "UTF-8,ASCII,JIS,EUC-JP,SJIS"
; 輸出緩衝區編碼轉換 (舊專案過渡用)
; output_handler = mb_output_handler
程式碼層面:資料庫連線 `SET NAMES utf8mb4` (MySQL) / `PGCLIENTENCODING=UTF8` (PostgreSQL) / `charset=UTF-8` (PDO DSN)。
| 層面 | 配置/代碼 | 說明 |
|---|---|---|
| JSP 頁面指令 | `<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>` | pageEncoding 決定 JSP 編譯時讀取編碼;contentType 決定輸出 HTTP 標頭 |
| Servlet 輸出 | `response.setContentType("text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8");` | 必在 `getWriter()` 前調用 |
| 請求參數解碼 (GET/POST) | Tomcat `server.xml` Connector 加 `URIEncoding="UTF-8" useBodyEncodingForURI="true"` 或 Filter: `request.setCharacterEncoding("UTF-8")` (必在 `getParameter()` 前) | GET 參數在 URL 經 URIEncoding 解碼;POST 經 request 編碼解碼 |
| 資料庫連線 | JDBC URL: `useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai` (MySQL) `charSet=UTF-8` (Oracle/PostgreSQL) | 連線層編碼協商 |
| 檔案讀寫 | `new InputStreamReader(is, "UTF-8")` / `Files.readString(path, StandardCharsets.UTF_8)` | 明確指定編碼,避免平台預設值 |
| 系統層面 (不推薦) | -Dfile.encoding=UTF-8 (JVM 啟動參數) | 影響全域預設,可能導致第三方庫行為異常,慎用 |