早期 J2ME 手機對字符編碼支援不一,網絡傳輸中文易亂碼。本文提供一套「服務端→客戶端 Unicode 轉義」+「客戶端→服務端 ISO-8859-1 透傳」的雙向兼容方案。
public static String gbEncoding(String gbString) {
char[] chars = gbString.toCharArray();
StringBuilder unicodeBytes = new StringBuilder();
for (char c : chars) {
String hex = Integer.toHexString(c);
if (hex.length() <= 2) hex = "00" + hex; // ASCII 補齊 4 位
unicodeBytes.append("\\u").append(hex);
}
return unicodeBytes.toString(); // 如:"中文" → "\u4e2d\u6587"
}
// 發送流程
String unicode = gbEncoding(value);
byte[] data = unicode.getBytes(); // 按平台默認編碼(通常 ISO-8859-1/UTF-8)轉字節
out.writeInt(data.length);
out.write(data);
private StringBuffer decodeUnicode(String dataStr) {
StringBuffer buffer = new StringBuffer();
int start = 0, end = 0;
while (start > -1) {
end = dataStr.indexOf("\\u", start + 2);
String charStr = (end == -1) ?
dataStr.substring(start + 2) :
dataStr.substring(start + 2, end);
char letter = (char) Integer.parseInt(charStr, 16);
buffer.append(letter);
start = end;
}
return buffer;
}
private void writeSjis(DataOutputStream out, String value) {
// 關鍵:按 ISO-8859-1 獲取字節,不做任何轉換
byte[] data = value.getBytes("ISO8859_1");
out.writeInt(data.length);
out.write(data);
}
原理:J2ME 字符內部為 Unicode,getBytes("ISO8859_1") 將低 8 位直接取出(高 8 位截斷),對於中文(BMP 字符)實際上丟失高位信息,但配合服務端反向還原可工作。
public static String isoToUtf(String iso) {
if (iso == null) return "";
try {
// 將 ISO-8859-1 字節重新解碼為 UTF-8 字符串
return new String(iso.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
return iso;
}
}
後續業務邏輯、數據庫存儲均基於 UTF-8。注意:SQL Server 等數據庫可能需額外按其內碼轉換。
| 維度 | 評價 |
|---|---|
| 通用性 | 只要手機支援 Unicode/GB2312 顯示即可工作 |
| 效率 | 非最高效(字符串膨脹、雙向轉換開銷),但可接受 |
| 可靠性 | 實測主流機型通過,避開了編碼支援差異陷阱 |
| 適用場景 | 早期 J2ME 專案、不支援 HTTPS/現代編碼協商的環境 |
UTF-8 端到端傳輸(需確認手機支援 getBytes("UTF-8"))DataOutputStream.writeUTF/readUTF(Modified UTF-8 格式)Content-Type: application/json; charset=utf-8)本方案作為歷史遺留項目維護或極度受限環境下的實用備選。