CNS11643 轉 UTF8 經驗

2024-03-21 工作雜記 CNS11643 Java

  • unicode: 萬國碼,設計上一共有17個平面。在第0的平面中,可以直接用一個 UTF-8 表示。
  • CNS11643: 中文標準交換碼,是中華民國國家標準11643號,簡稱CNS 11643,舊名通用漢字標準交換碼,是中華民國政府為中文資訊處理製定的字元編碼方案,與許多學術圖書館係統採用的CCCII同屬於中文交換碼。CSIC基於ISO 2022定義,和ASCII相容,其EUC版本為EUC-TW。

最近工作上碰到 Oracle 編碼是 US7ASII , 而存放的有中文資料,於是遇到了轉碼問題。對方的轉碼在Java邏輯大緻上如下:

  1. 使用 ISO-8859-1 方式讀取資料庫
  2. 解析成字: 兩個位元碼
  3. 在將兩個位元碼搜尋對應的 CNS11643 編碼
  4. 在將 CNS11643 編碼對應成 unicode

在處理這塊之前其實我分不清處什麼是unicodeUTF-8,後來才知道 UTF 是 Unicode Transformation Format 的縮寫。UTF 主要是為了解決不同平臺傳輸間的問題?

在這次經驗中遇到了CNS11643 對找錶 中 unicode 在 Java 如何處理。我這邊以 𡪨 這個字為例。

以下是這個字的編碼資訊:

  • CNS11643 網站中 Unicode: 5F35
  • HTML Entity: 張張
  • UTF-8 Encoding (hex): 0xE5 0xBC 0xB5
  • UTF-16 Encoding (hex): 0x5F35
  • UTF-32 Encoding (hex): 0x00005F35

𡪨

以下是這個字的編碼資訊:

  • CNS11643 網站中 Unicode: 21AA8
  • UTF-8 (hex) 0xF0 0xA1 0xAA 0xA8 (f0a1aaa8)
  • UTF-8 (binary) 11110000:10100001:10101010:10101000
  • UTF-16 (hex) 0xD846 0xDEA8 (d846dea8)
  • UTF-16 (decimal) 55,366 57,000
  • UTF-32 (hex) 0x00021AA8 (21aa8)
  • UTF-32 (decimal) 137,896
  • C/C++/Java source code “\uD846\uDEA8”

在 Java 中可以很輕易處理

String unicodeString = "\u5F35";
System.out.println(unicodeString);

然而在處理𡪨 時就無法,因此必須改用UTF-32 顯示處理,實際處理方式如下:


String hexString = "21AA8";

// 假設你有一個UTF-32編碼的碼點 21AA8
int codePoint = Integer.parseInt(hexString.toString(), 16);

// 創建ByteBuffer以容納UTF-32編碼的碼點
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.putInt(codePoint);
// 將ByteBuffer從寫模式切換到讀模式
byteBuffer.flip();

// 使用UTF-32編碼創建字符串
Charset utf32Charset = Charset.forName("UTF-32");
String utf32String = utf32Charset.decode(byteBuffer).toString();

// 將UTF-32字符串轉換為UTF-8編碼的字節序列
byte[] utf8Bytes = utf32String.getBytes(StandardCharsets.UTF_8);

String showString =  String(utf8Bytes, StandardCharsets.UTF_8);

return showString;

所以在處理 CNS11643 轉 Unicode 的處理方式建議直接從 UTF-32 直接著手比較可以預防第零字面以外的字。

參考資料