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

Java 中文亂碼終極指南:從編碼原理到控制台、JSP、請求參數、數據庫全鏈路排查

     編輯:Java 相關知識

前言:亂碼本質是「編解碼不匹配」

Java 內部統一用 UTF-16 (Unicode) 存儲字符。字符流經「輸入流 → 解碼為 Unicode → 內存 → 編碼為目標編碼 → 輸出流」兩次轉碼。任一環節編碼不一致,即產生亂碼。本文按「控制台、JSP 靜態/動態、Request 參數 (GET/POST)、數據庫」五大場景,給出原理分析、排查步驟、標準解法。

場景一:Eclipse 控制台輸出亂碼

現象

String text = "大家好";
System.out.println(text); // 控制台顯示 ???? 或 

原理鏈路

  1. 源文件保存為 UTF-8;
  2. Eclipse 內置編譯器按文件編碼編譯,字節碼存 Unicode;
  3. 運行時 JVM 讀取字節碼無轉碼,內存中為正確 Unicode;
  4. System.out.println 使用 PrintStream,默認按 平台默認編碼 (GBK) 將 Unicode 編碼為字節輸出;
  5. Eclipse 控制台視圖編碼設置為 UTF-8 (默認繼承 Workspace),按 UTF-8 解碼顯示 → 亂碼。

解決

Run Configurations → Common → Encoding 勾選 GBK (需先在 Workspace 設置添加 GBK 選項),或代碼中指定 System.setOut(new PrintStream(System.out, true, "UTF-8")) 統一輸出編碼。

場景二:JSP 靜態中文亂碼

四次編解碼鏈路

  1. JSP 文件保存編碼 (如 UTF-8);
  2. Tomcat 讀取 JSP 編譯,依賴 pageEncoding 屬性;
  3. Tomcat 響應輸出,依賴 contentType="text/html;charset=UTF-8",寫入 HTTP Header;
  4. 瀏覽器按 Header charset 解碼渲染。

標準模板

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

三處 UTF-8 必須一致,且 pageEncoding 告知 Tomcat 讀取編碼,contentType 告知瀏覽器解碼編碼。

場景三:JSP 讀取文件顯示亂碼

錯誤代碼

BufferedReader reader = new BufferedReader(new FileReader("D:\\test.txt")); // FileReader 默認平台編碼 GBK
String content = reader.readLine();

原因

文件為 UTF-8,但 FileReader 硬編碼使用平台默認編碼 (GBK) 讀取,導致內存中 Unicode 錯誤。

正確姿勢

InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\test.txt"), "UTF-8");
BufferedReader reader = new BufferedReader(isr);

或啟動參數 -Dfile.encoding=UTF-8 (不推薦,影響全局)。

場景四:Request 參數中文亂碼 (核心難點)

GET 與 POST 本質不同

維度GETPOST
參數位置URL Query StringRequest Body
瀏覽器編碼IE6: 系統默認 GBK; IE7+: 頁面編碼; 現代瀏覽器: 頁面編碼頁面編碼 (由 Content-Type charset 決定)
Tomcat 解碼URIEncoding (server.xml),默認 ISO-8859-1request.setCharacterEncoding() (需在首次 getParameter 前調用)
Filter 可攔截無效 (Tomcat 早期解析)有效

統一解決方案 (Tomcat 8+ 推薦)

  1. server.xml 配置 <Connector URIEncoding="UTF-8" useBodyEncodingForURI="true" />:
    useBodyEncodingForURI="true" 使 GET 也使用 request.setCharacterEncoding 設置的編碼;
  2. 編寫 CharacterEncodingFilter (Spring 提供 org.springframework.web.filter.CharacterEncodingFilter):
    強制 request.setCharacterEncoding("UTF-8") 並 response.setCharacterEncoding("UTF-8"),映射 /*,forceEncoding=true;
  3. JSP/HTML 頁面統一 charset=UTF-8;
  4. 前端 AJAX 設置 contentType: "application/x-www-form-urlencoded; charset=UTF-8"。

歷史版本兼容 (Tomcat 7/6)

若無法升級,需單獨配置 URIEncoding="UTF-8" 處理 GET,Filter 處理 POST,並確保頁面編碼與 URIEncoding 一致 (均為 UTF-8 或均為 GBK)。

場景五:數據庫中文亂碼

  • JDBC URL 顯式指定編碼:jdbc:mysql://host:3306/db?characterEncoding=UTF-8&useUnicode=true&serverTimezone=Asia/Shanghai;
  • 表/庫/列編碼統一為 utf8mb4 (支持 Emoji);
  • 連接池屬性 connectionInitSqls 設置 SET NAMES utf8mb4。

總結:亂碼排查萬能公式

  1. 確定 源頭編碼 (文件保存、頁面 charset、瀏覽器發送、DB 列編碼);
  2. 確定 中間處理編碼 (編譯器、Tomcat 解碼 URI/Body、JDBC 驅動);
  3. 確定 終端編碼 (控制台視圖、瀏覽器渲染、日誌文件);
  4. 全鏈路統一為 UTF-8,並在構建腳本、容器鏡像、CI/CD 中固化。

堅持「指定編碼讀取 → Unicode → 指定編碼輸出」原則,拒絕 new String(bytes, "ISO-8859-1") 類暴力轉碼,從源頭消除亂碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved