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

Java 字符編碼全景解析:從基礎概念到 URL/數據庫/前端實戰

     編輯:Java 相關知識

編碼體系速覽

編碼類型覆蓋範圍特點
ISO-8859-1單字節0-255西歐語系,Java 默認網絡傳輸編碼
GB2312/GBK雙字節簡體/簡繁中文中文 Windows 默認,兼容 ASCII
UTF-16 (Unicode)定長雙字節全字符集Java 內存/字符串內部編碼
UTF-8變長 1-4 字節全字符集兼容 ASCII,網絡傳輸/存儲首選

Java 核心 API 操作

// String → byte[] (編碼)
byte[] utf8 = "中文".getBytes(StandardCharsets.UTF_8);   // [0xE4,0xB8,0xAD,0xE6,0x96,0x87]
byte[] gbk  = "中文".getBytes("GBK");                      // [0xD6,0xD0,0xCE,0xC4]

// byte[] → String (解碼)
String s1 = new String(utf8, StandardCharsets.UTF_8);     // "中文"
String s2 = new String(gbk, "GBK");                       // "中文"

// 關鍵:編解碼必須成對,否則亂碼
// 可逆性:new String(str.getBytes("UTF-8"), "UTF-8") == str

Web 應用編碼鏈路

  1. 頁面編碼:JSP 頭部 <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
  2. 請求解碼:request.setCharacterEncoding("UTF-8")(必須在首次 getParameter() 前調用,僅對 POST 有效)
  3. 響應編碼:response.setCharacterEncoding("UTF-8") + response.setContentType("text/html;charset=UTF-8")
  4. 瀏覽器渲染:HTML `` 兜底

表單提交編碼陷阱

  • GET 請求參數在 URL,受瀏覽器/服務器配置影響大,建議統一 POST 或显式處理
  • Tomcat 8+ 默認 URIEncoding=UTF-8,舊版需在 ``
  • Filter 統一設置:SetCharacterEncodingFilter (Spring 内置)

文件與編譯編碼

  • 源文件保存編碼 = 編譯器讀取編碼 = `javac -encoding UTF-8` / IDE 設置
  • JSP 部署跨平台必須指定 `pageEncoding`,否則編譯亂碼
  • 屬性文件:Java 9+ 支持 UTF-8 `.properties`,舊版需 `native2ascii` 轉義

數據庫編碼

-- MySQL 建庫建表
CREATE DATABASE app DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE t (c VARCHAR(100)) CHARSET=utf8mb4;

-- JDBC 連接串
jdbc:mysql://host:3306/app?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull

utf8mb4 支持 Emoji(4 字節),utf8 僅 3 字節。

URL 編碼難題與解決方案

問題根源

IE「總是使用 UTF-8 發送 URL」選項導致同一鏈接到達服務器編碼不同:

  • 開啟:`%E4%B8%AD%E6%96%87.html?a=%E4%B8%AD%E6%96%87` (UTF-8 + URLEncode)
  • 關閉:中文直接按系統編碼(GBK)發送,不 URLEncode

智能判斷解碼器


public static String decodeUrlParam(String raw, String defaultCharset) {
    try {
        byte[] bytes = raw.getBytes("ISO-8859-1"); // 還原 Servlet 容器按 ISO-8859-1 解碼後的字節
        if (isValidUtf8(bytes)) {
            return new String(bytes, "UTF-8");
        }
        return new String(bytes, defaultCharset); // 如 GBK
    } catch (UnsupportedEncodingException e) {
        throw new IllegalStateException(e);
    }
}

private static boolean isValidUtf8(byte[] bytes) {
    int i = 0;
    while (i < bytes.length) {
        int b = bytes[i++] & 0xFF;
        if (b < 0x80) continue; // ASCII
        int expected;
        if ((b & 0xE0) == 0xC0) expected = 1;
        else if ((b & 0xF0) == 0xE0) expected = 2;
        else if ((b & 0xF8) == 0xF0) expected = 3;
        else return false;
        if (i + expected > bytes.length) return false;
        for (int j = 0; j < expected; j++) {
            if ((bytes[i++] & 0xC0) != 0x80) return false;
        }
    }
    return true;
}

注意:極少數 GBK 字節序列誤判為合法 UTF-8(如「學習」),可結合 `Accept-Language` 頭輔助判斷。

工具鏈與運維檢查清單

  • Linux 環境變量:`LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8`
  • 掛載 NTFS 指定 `iocharset=utf8`
  • SecureCRT/終端設置 UTF-8,MySQL 客端同步
  • 記事本保存 UTF-8 帶 BOM 會干擾解析,Linux `vi` 保存無 BOM
  • 統一項目編碼:Maven `UTF-8`
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved