| 術語 | 定義 |
|---|---|
| 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.forName(String):獲取具體實例,拋出 UnsupportedCharsetException。Charset.availableCharsets():列出所有可用字符集。charset.newEncoder() / newDecoder():獲取編碼器/解碼器實例。charset.encode(CharBuffer/String) / decode(ByteBuffer):便利方法,一次性完成轉換。charset.contains(Charset):判斷是否包含另一字符集(如 UTF-16 包含 US-ASCII)。兩者皆為有狀態的轉換引擎,核心流程:
reset():重置狀態。encode(CharBuffer in, ByteBuffer out, boolean endOfInput) / decode(ByteBuffer in, CharBuffer out, boolean endOfInput) 處理資料塊。flush(ByteBuffer/CharBuffer out):刷新剩餘狀態(如 UTF-16 的 BOM)。返回 CoderResult 指示結果:UNDERFLOW(輸入耗盡)、OVERFLOW(輸出滿)、malformed(輸入不合法)、unmappable(無法映射)。
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();
}
步驟:
Charset,實作 contains、newEncoder、newDecoder。CharsetEncoder,實作 encodeLoop:先對字符執行 Rot13 置換,再委託給基礎編碼器(如 UTF-8)。CharsetDecoder,實作 decodeLoop:先委託基礎解碼器,再對結果執行 Rot13 還原。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 提供了完整、靈活的編碼解碼框架:
雖然多數開發者僅需 StandardCharsets.UTF_8,但理解底層機制對處理異構系統整合、舊系統遷移、自定義協定至關重要。