J2ME 中文問題的本質在於寫入與讀取時使用的字元編碼不匹配。根據 MIDP 規範,所有支援 J2ME 的裝置強制支援 UTF-8,因此統一採用 UTF-8 進行字串與位元組陣列互轉,即可徹底解決儲存記錄集(RMS)、網路傳輸、資源檔讀取等場景的中文亂碼問題。
直接使用 String.getBytes() 或 new String(byte[]) 會依賴平台預設編碼(通常為 ISO-8859-1),導致中文資料損壞:
// ❌ 錯誤做法
byte[] data = "中文".getBytes(); // 平台預設編碼
String s = new String(data); // 平台預設解碼
DataOutputStream.writeUTF() 與 DataInputStream.readUTF() 內建採用修改版 UTF-8(Modified UTF-8),是 J2ME 處理中文的標準方式:
import java.io.*;
public final class ChineseCodec {
private ChineseCodec() {} // 工具類禁止實例化
/** 字串 → 位元組陣列 (UTF-8) */
public static byte[] toBytes(String s) {
if (s == null) return new byte[0];
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeUTF(s); // 寫入修改版 UTF-8
dos.flush();
return baos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("UTF-8 編碼失敗", e);
}
}
/** 位元組陣列 → 字串 (UTF-8) */
public static String toString(byte[] bytes) {
if (bytes == null || bytes.length == 0) return "";
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
DataInputStream dis = new DataInputStream(bais);
return dis.readUTF(); // 讀取修改版 UTF-8
} catch (IOException e) {
throw new RuntimeException("UTF-8 解碼失敗", e);
}
}
}
// 寫入
RecordStore rs = RecordStore.openRecordStore("UserData", true);
byte[] data = ChineseCodec.toBytes("玩家名稱: 王小明");
rs.addRecord(data, 0, data.length);
// 讀取
byte[] record = rs.getRecord(recordId);
String text = ChineseCodec.toString(record); // 正確還原中文
HttpConnection conn = (HttpConnection) Connector.open(url);
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
OutputStream os = conn.openOutputStream();
os.write(ChineseCodec.toBytes("msg=中文訊息&id=123"));
os.flush();
InputStream is = getClass().getResourceAsStream("/res/config.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) > 0) baos.write(buf, 0, len);
String content = ChineseCodec.toString(baos.toByteArray());
writeUTF/readUTF 將 \\u0000 編碼為兩位元組 0xC0 0x80,而非標準 UTF-8 的單一 0x00。雙端必須同為 J2ME 或同用 DataInput/OutputStream 才能互通。File Encoding = UTF-8)。統一使用 DataOutputStream.writeUTF() / DataInputStream.readUTF() 處理所有字串↔位元組轉換,是 J2ME 中文問題的唯一標準解。拒絕 getBytes()、new String(bytes)、String.getBytes("UTF-8") 等非標準寫法,即可在 RMS、網路、資源檔全場景實現中文零亂碼。