首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 字元編碼完全指南:從亂碼根因到最佳實踐

     編輯:Java 相關知識

編碼基礎知識

編碼類型覆蓋範圍特點
ISO-8859-1 (Latin-1)單位元組西歐語系0-255 直接映射,Java 預設網路編碼
GB2312 / GBK / GB18030雙位元組 (兼容 ASCII)簡體/繁體中文中文最節省空間 (2 bytes/字),GBK 支援繁體
UTF-16 / UCS-2固定雙位元組 (含 BOM)所有 UnicodeJava 內部 `char`/`String` 採用 UTF-16
UTF-8變長 (1-4 bytes)所有 UnicodeASCII 兼容、無 BOM、網路傳輸/儲存首選

Java 核心 API 轉換機制


// String (UTF-16) → byte[] (指定編碼)
byte[] utf8Bytes = "中文".getBytes(StandardCharsets.UTF_8);  // [E4, B8, AD, E6, 96, 87]
byte[] gbkBytes  = "中文".getBytes("GBK");                    // [D6, D0, CE, C4]

// byte[] → String (指定編碼解碼)
String s1 = new String(utf8Bytes, StandardCharsets.UTF_8); // 正確
String s2 = new String(gbkBytes, "GBK");                   // 正確
String s3 = new String(gbkBytes, StandardCharsets.ISO_8859_1); // 亂碼:?

鐵律: 編碼與解碼必須完全對稱,否則產生亂碼或資料損失 ( 替換字元)。

Web 應用全鏈路編碼控制

1. 請求端

  • POST 表單:`request.setCharacterEncoding("UTF-8")` 必須在 **任何 `getParameter()` 之前** 呼叫。
  • GET 參數:Tomcat 8+ 需在 `server.xml` 設定 `` 或 Spring Boot `server.tomcat.uri-encoding=UTF-8`。

2. 伺服器端處理


// Spring Boot 自動配置已處理,手動 Servlet 需:
@WebFilter("/*")
public class EncodingFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        req.setCharacterEncoding("UTF-8");
        res.setCharacterEncoding("UTF-8");
        res.setContentType("text/html;charset=UTF-8");
        chain.doFilter(req, res);
    }
}

3. 回應端

  • JSP:`<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>`
  • Spring MVC:`@Controller` 方法回傳 `@ResponseBody` 自動 UTF-8,視圖解析器需設定 `characterEncoding`。
  • HTTP Header:`Content-Type: application/json;charset=UTF-8`

4. 資料庫層


# MySQL 8.0+ 預設 utf8mb4 (支援 Emoji)
# 連線字串
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Taipei

# 表建立
CREATE TABLE t (c VARCHAR(100)) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

檔案與原始碼編碼

  • 原始碼:IDE 專案編碼設為 UTF-8,`javac -encoding UTF-8`。
  • 屬性檔:Java 9+ `Properties.load(Reader)` 支援 UTF-8 直接讀取;舊版需 `native2ascii` 轉 Unicode 轉義。
  • BOM 陷阱:Windows 記事本儲存 UTF-8 帶 BOM (EF BB BF),Java 讀取會將 BOM 視為內容,建議用「UTF-8 無 BOM」或程式碼跳過前 3 位元組。

URL 編碼特殊規則


// 應用層編碼 (非整個 URL)
String param = "中文/參數";
String encoded = URLEncoder.encode(param, StandardCharsets.UTF_8); // %E4%B8%AD%E6%96%87%2F%E5%8F%83%E6%95%B8
String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8);

注意:`URLEncoder` 將空格編為 `+` (表單標準),URL 路徑段落應用 `UriUtils.encodePathSegment` (Spring) 或手動將 `+` 改 `%20`。

亂碼診斷三步法

  1. 確認資料源頭編碼:資料庫、檔案、HTTP 請求、第三方 API 實際編碼為何?
  2. 追蹤轉換路徑:每一層 `getBytes(charset)` / `new String(bytes, charset)` 是否對稱?
  3. 定位斷點:在關鍵轉換點印出 `bytes` 十六進位 (Hex),對照碼表驗證。

現代最佳實踐清單

  1. 全鏈路 UTF-8:原始碼、資料庫、HTTP、檔案、日誌統一 UTF-8 (MySQL 用 `utf8mb4`)。
  2. 顯式指定 Charset:所有 `getBytes()`、`new String()`、`InputStreamReader`、`OutputStreamWriter` 必帶 `StandardCharsets.UTF_8`。
  3. Spring Boot 零配置:預設即 UTF-8,僅需確認 `server.tomcat.uri-encoding=UTF-8` (GET 參數)。
  4. 拒絕 ISO-8859-1 中轉:舊代碼常見 `new String(bytes, "ISO-8859-1")` 再 `getBytes("GBK")`,極易出錯,重構移除。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved