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

Java 字元編碼與解碼深度解析:Charset、Encoder、Decoder 與自定義字符集實作

     編輯:Java 程式設計入門

核心概念釐清

術語定義
Character Set (字符集)抽象字符集合,如 Unicode 碼位。
Coded Character Set (編碼字符集)字符對應數值的映射表,如 US-ASCII、UTF-8。
Character Encoding Scheme (字符編碼方案)將編碼值轉換為位元組序列的規則,如 UTF-8 將碼位編碼為 1-4 位元組。
Charset (Java 中的字符集)封裝「編碼字符集」與「編碼方案」的組合,對應 java.nio.charset.Charset。

標準字符集編碼示例

同一字串 "¿Mañana?" 在不同 Charset 下的位元組表示:

US-ASCII   : 20 3F 4D 61 3F 61 6E 61 3F   (無法表示的字符變 ?)
ISO-8859-1 : 20 BF 4D 61 F1 61 6E 61 3F
UTF-8      : 20 C2 BF 4D 61 C3 B1 61 6E 61 3F
UTF-16BE   : 00 20 00 BF 00 4D 00 61 00 F1 00 61 00 6E 00 61 00 3F
UTF-16LE   : 20 00 BF 00 4D 00 61 00 F1 00 61 00 6E 00 61 00 3F 00
UTF-16     : FE FF 00 20 00 BF 00 4D 00 61 00 F1 00 61 00 6E 00 61 00 3F (含 BOM)

Charset 核心 API

  • Charset.forName(String):獲取具體實例,拋出 UnsupportedCharsetException。
  • Charset.availableCharsets():列出所有可用字符集。
  • charset.newEncoder() / newDecoder():獲取編碼器/解碼器實例。
  • charset.encode(CharBuffer/String) / decode(ByteBuffer):便利方法,一次性完成轉換。
  • charset.contains(Charset):判斷是否包含另一字符集(如 UTF-16 包含 US-ASCII)。

CharsetEncoder / CharsetDecoder 狀態機模型

兩者皆為有狀態的轉換引擎,核心流程:

  1. reset():重置狀態。
  2. 重複呼叫 encode(CharBuffer in, ByteBuffer out, boolean endOfInput) / decode(ByteBuffer in, CharBuffer out, boolean endOfInput) 處理資料塊。
  3. flush(ByteBuffer/CharBuffer out):刷新剩餘狀態(如 UTF-16 的 BOM)。

返回 CoderResult 指示結果:UNDERFLOW(輸入耗盡)、OVERFLOW(輸出滿)、malformed(輸入不合法)、unmappable(無法映射)。

錯誤處理策略 (CodingErrorAction)

  • REPORT(預設):返回 CoderResult 讓調用者處理。
  • IGNORE:跳過錯誤輸入。
  • REPLACE:以替換序列取代(預設 ? 或 \uFFFD)。

完整解碼範例:通道管道式處理

public static void decodeChannel(ReadableByteChannel in, Writer out, Charset cs) throws IOException {
    CharsetDecoder dec = cs.newDecoder()
        .onMalformedInput(CodingErrorAction.REPLACE)
        .onUnmappableCharacter(CodingErrorAction.REPLACE);
    ByteBuffer bb = ByteBuffer.allocateDirect(16 * 1024);
    CharBuffer cb = CharBuffer.allocate(57);
    CoderResult cr = CoderResult.UNDERFLOW;
    boolean eof = false;
    while (!eof) {
        if (cr.isUnderflow()) {
            bb.clear();
            eof = in.read(bb) == -1;
            bb.flip();
        }
        cr = dec.decode(bb, cb, eof);
        if (cr.isOverflow()) drain(cb, out);
    }
    while (dec.flush(cb).isOverflow()) drain(cb, out);
    drain(cb, out);
    in.close(); out.flush();
}

自定義字符集實作:Rot13 範例

步驟:

  1. 繼承 Charset,實作 contains、newEncoder、newDecoder。
  2. 繼承 CharsetEncoder,實作 encodeLoop:先對字符執行 Rot13 置換,再委託給基礎編碼器(如 UTF-8)。
  3. 繼承 CharsetDecoder,實作 decodeLoop:先委託基礎解碼器,再對結果執行 Rot13 還原。
  4. 實作 CharsetProvider,在 META-INF/services/java.nio.charset.spi.CharsetProvider 註冊全類名。

關鍵程式碼片段:

// Rot13Encoder.encodeLoop
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
    CharBuffer tmp = CharBuffer.allocate(in.remaining());
    while (in.hasRemaining()) tmp.put(in.get());
    tmp.rewind();
    rot13(tmp); // 原地修改
    baseEncoder.reset();
    CoderResult cr = baseEncoder.encode(tmp, out, true);
    in.position(in.position() - tmp.remaining()); // 同步消費進度
    return cr;
}

總結

java.nio.charset 提供了完整、靈活的編碼解碼框架:

  • Charset:字符集抽象,工廠入口。
  • CharsetEncoder/Decoder:可控的流式轉換引擎,支援錯誤處理、緩衝區管理。
  • CharsetProvider SPI:可插拔擴展機制,支援第三方字符集。

雖然多數開發者僅需 StandardCharsets.UTF_8,但理解底層機制對處理異構系統整合、舊系統遷移、自定義協定至關重要。

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