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

J2ME 中文編碼全解析:ISO/UTF-8/Unicode 區別、存儲傳輸最佳實踐與調試顯示難題

     編輯:J2ME

三大編碼格式對比 (以「摩托羅拉」為例)

編碼Hex 數據特徵中文佔用
ANSI (GBK/GB2312) C4 A6 CD D0 C2 DE C0 AD 無 BOM,每字節 > 0x80 2 字節
Unicode (UTF-16LE) FF FE 69 64 58 62 57 7F C9 62 BOM: FF FE,固定 2 字節/字符 2 字節
UTF-8 EF BB BF E6 91 A9 E6 89 98 E7 BD 97 E6 8B 89 BOM: EF BB BF,英文 1 字節,中文 3 字節 3 字節

核心難題:J2ME 中文存儲、傳輸、調試顯示

J2ME 環境下,直接操作中文 String 進行 RMS 存儲、網絡傳輸、System.out.println 調試,極易出現亂碼。根因:

  • RMS/網絡傳輸以字節流為單位,字符編碼轉換由開發者控制。
  • 模擬器/真機控制台編碼往往非 UTF-8,導致調試輸出亂碼。

最佳實踐:統一使用 DataOutputStream/DataInputStream + UTF-8

// 寫入: String -> byte[] (Modified UTF-8)
public static byte[] stringToBytes(String s) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeUTF(s); // 寫入長度(2字節) + Modified UTF-8 字節
        return baos.toByteArray();
    } catch (IOException e) { return null; }
}

// 讀取: byte[] -> String
public static String bytesToString(byte[] b, int offset, int len) {
    try {
        ByteArrayInputStream bais = new ByteArrayInputStream(b, offset, len);
        DataInputStream dis = new DataInputStream(bais);
        return dis.readUTF(); // 解析 Modified UTF-8
    } catch (IOException e) { return null; }
}

關鍵點:writeUTF/readUTF 使用 Modified UTF-8 (補碼長度前綴),寫讀必須配對使用,不可與標準 UTF-8 混用。

應用場景示例

1. RMS 存儲歌詞/配置

// 存
byte[] data = stringToBytes(lrcText);
recordStore.addRecord(data, 0, data.length);

// 取
byte[] data = recordStore.getRecord(recordId);
String lrc = bytesToString(data, 0, data.length);

2. UDP/TCP 網絡傳輸中文

// 發送端
byte[] payload = stringToBytes(text);
Datagram dg = conn.newDatagram(payload, payload.length, addr);
conn.send(dg);

// 接收端
Datagram dg = conn.newDatagram(maxSize);
conn.receive(dg);
String text = bytesToString(dg.getData(), dg.getOffset(), dg.getLength());

調試顯示難題:為什麼 System.out.println 中文全是問號?

模擬器/真機控制台編碼通常為平台默認 (如 GBK、Cp1252),而 Java 內部 String 為 UTF-16。直接打印會經過 JVM 默認編碼轉換,導致不可讀。

實測對比:三種 getBytes 參數的接收端表現

發送端 getBytes 參數接收端 byte[] 內容模擬器屏幕顯示控制台 System.out
無參數 (平台默認) 12 bytes,每漢字 2 bytes,值為 ANSI 編碼 亂碼 ✅ 正常
"ISO10646" 拋出 UnsupportedEncodingException — —
"ISO8859_1" 6 bytes,全 0x3F ('?') 全問號 全問號

調試中文的可行方案

  1. 在屏幕上繪製:g.drawString(str, x, y, 0),LCDUI 內部處理字體渲染,最直觀。
  2. 轉十六進制輸出:for(byte b: str.getBytes()) System.out.print(Integer.toHexString(b&0xFF)+" ");,觀察原始字節排查編碼。
  3. 使用支持 UTF-8 的遠程調試工具:如 WTK 監控台、IDE 遠程調試器。

總結原則

  1. 存儲/傳輸:統一用 DataOutputStream.writeUTF / DataInputStream.readUTF (Modified UTF-8),寫讀配對,跨平台無亂碼。
  2. 文件編碼:源碼文件保存為 UTF-8 (IDE 設置),編譯器正確解析字符串字面量。
  3. 調試顯示:不依賴控制台,優先在模擬器屏幕繪製驗證;必要時輸出 Hex 碼分析。
  4. 避免:直接 String.getBytes() 發送、new String(byte[]) 解析、混用多種編碼參數。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved