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

J2ME 中文編碼完整攻略:從亂碼根因到 RMS/網路/資源檔/JAD 全場景解決方案

     編輯:J2ME

核心觀念:編碼 ≠ 字型

編碼決定「字元 → 位元組序列」的映射規則;字型決定「字元 → 字形」的繪製規則。亂碼 99% 是編碼不匹配,非字型缺失。

一、常見編碼速查表

編碼類型中文支援Java 名稱別名備註
ASCII / ISO-8859-1單位元組❌ISO8859_1, 8859_1預設編碼,中文全變 ?
GB2312 / GBK / GB18030雙位元組 (DBCS)✅ 簡體GB2312, GBK, GB18030, cp936國標,GBK/18030 為超集
Big5 / Big5-HKSCS雙位元組✅ 繁體Big5, Big5-HKSCS, cp950繁體中文主流
UTF-8可變長 (1~3 bytes)✅ 全 UnicodeUTF-8, UTF8, utf8網路傳輸、JAD、XML 標準
UTF-16 (UCS-2)固定 2 bytes✅ BMP 字元UTF-16, UCS-2, UnicodeBigUnmarkedNokia 常用 "ucs-2"

二、CLDC/MIDP 核心 API

// 解碼:byte[] → String
String s = new String(byteArr, "GB2312");

// 編碼:String → byte[]
byte[] b = s.getBytes("UTF-8");

// 異常:UnsupportedEncodingException → 裝置不支援該編碼

// 偵測裝置支援度
boolean supported(String enc) {
    try { "測試".getBytes(enc); return true; }
    catch (UnsupportedEncodingException e) { return false; }
}

// DataInput/OutputStream 的 UTF-8 變體 (長度前綴 2 bytes)
DataOutputStream dos = new DataOutputStream(out);
dos.writeUTF(str);  // 寫入長度 + UTF-8 bytes
DataInputStream dis = new DataInputStream(in);
String s2 = dis.readUTF();

三、四大實戰場景解決方案

1. RMS 本地儲存

// 方案 A:UTF-8 (通用、無需偵測)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF("中文內容");
rs.addRecord(bos.toByteArray(), 0, bos.size());

// 讀回
byte[] data = rs.getRecord(id);
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
String s = dis.readUTF();

// 方案 B:GB2312 (省空間,需先確認支援)
byte[] b = "中文".getBytes("GB2312");
rs.addRecord(b, 0, b.length);
// 讀回
String s = new String(rs.getRecord(id), "GB2312");

2. 資源檔 (getResourceAsStream) 讀取中文

檔案編碼讀取代碼關鍵點
UTF-8new String(bytes, "UTF-8")最通用
UTF-16LE (低位在前)new String(bytes, "UTF-16LE") 或手動解碼 + BOM FF FENokia 稱 "ucs-2" 實為 LE
UTF-16BE (高位在前)new String(bytes, "UTF-16BE") 或 "ucs-2" (視裝置)需確認 BOM FE FF
GB2312/Big5new String(bytes, "GB2312")需裝置支援

實戰技巧:文字編輯器 (Notepad++/UltraEdit) 另存新檔時選編碼;打包進 JAR 前用 hexdump 確認 BOM 與位元組序。

3. 網路傳輸 (HTTP / Socket / XML)

  • HTTP:回應標頭 Content-Type: text/plain; charset=UTF-8,客戶端讀標頭決定解碼。
  • Socket:雙方約定編碼 (建議 UTF-8),或在協議頭帶 1 byte 編碼 ID。
  • XML (kXML2):parser.setInput(is, "UTF-8");若 null 則自動偵測 XML 宣告 。

4. JAD 檔案中文

  1. JAD 必須 以 UTF-8 編碼儲存 (UltraEdit / Notepad++ → 「另存為 UTF-8 無 BOM」)。
  2. OTA 下載時,伺服器回應標頭必須含 Content-Type: text/vnd.sun.j2me.app-descriptor; charset=UTF-8,否則 Nokia S40 等裝置安裝後顯示亂碼。
  3. Manifest.mf 同理,建議同步用 UTF-8。

四、編碼互轉最佳實踐

// 任意支援編碼間互轉:以 UTF-8 為中介
String unicode = new String(gbBytes, "GB2312");   // 解碼
byte[] utf8Bytes = unicode.getBytes("UTF-8");     // 編碼

// 直接轉換 (不建議,易出錯)
// byte[] big5 = new String(gbBytes, "GB2312").getBytes("Big5");

原則:解碼用來源編碼,編碼用目標編碼,中介用 String (內部 UTF-16)。

五、裝置不支援目標編碼時的三條出路

  1. 內建映射表:只處理少量固定字串 (如選單項),以 Hashtable 存預編碼結果,佔 ~幾 KB。
  2. 代理伺服器轉碼:客戶端請求 → 代理 (Tomcat/Servlet) 轉碼 → 回傳 UTF-8,客戶端只需支援 UTF-8。
  3. 放棄該編碼:統一改用 UTF-8 或裝置支援的編碼,源頭 (後台 CMS、資料庫) 同步調整。

六、除錯檢查清單

現象可能原因驗證方法
全問號 ????編碼不支援 / 解碼錯誤印出 byte[] 十六進位,對照編碼表
半亂碼 (部分正常)資料截斷 / 奇數位元組截斷 (DBCS)檢查長度是否為偶數
方塊 □ / 缺字字型無對應字形換支援 Unicode 字型或用位圖字體
JAD 安裝後亂碼伺服器未送 charset=UTF-8抓包檢查 Content-Type 標頭

結語

J2ME 中文亂碼本質是「編碼協議不一致」。建立「來源編碼 → 統一內部 Unicode (String) → 目標編碼」的標準化流程,配合 UnsupportedEncodingException 自動偵測裝置能力,即可覆蓋 99% 實戰場景。記住:UTF-8 是通用橋樑,JAD/HTTP/XML 強制 UTF-8,本地儲存視空間選 GB2312/Big5。

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