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

Java ME 中文編碼完全指南:從編碼原理到 RMS/網路/資源/JAD 全場景實戰 (修訂版)

     編輯:J2ME

前言

本文為 J2ME 中文編碼完整攻略 的修訂補充版,針對實戰中易踩的坑補充細節,並增加「編碼自動偵測工具類」、「MIDP 3.0 / Java ME 8 新特性」與「Kotlin/Scala 移植提示」。

一、編碼自動偵測與統一工具類

public final class EncodingUtil {
    private EncodingUtil() {}

    /** 偵測裝置支援的編碼列表 */
    public static String[] detectSupportedEncodings() {
        String[] candidates = {"UTF-8", "GB2312", "GBK", "GB18030", "Big5", "Big5-HKSCS",
                               "UTF-16LE", "UTF-16BE", "ISO-8859-1", "US-ASCII"};
        Vector v = new Vector();
        for (String enc : candidates) {
            if (isSupported(enc)) v.addElement(enc);
        }
        String[] r = new String[v.size()];
        v.copyInto(r);
        return r;
    }

    public static boolean isSupported(String encoding) {
        try { "測試".getBytes(encoding); return true; }
        catch (UnsupportedEncodingException e) { return false; }
    }

    /** 安全轉碼:來源編碼 → 目標編碼,失敗回傳原 byte[] */
    public static byte[] transcode(byte[] src, String fromEnc, String toEnc) {
        try {
            String s = new String(src, fromEnc);
            return s.getBytes(toEnc);
        } catch (Exception e) { return src; }
    }

    /** 讀取資源檔自動偵測編碼 (支援 BOM) */
    public static String readResourceString(String resPath) throws IOException {
        InputStream is = EncodingUtil.class.getResourceAsStream(resPath);
        if (is == null) throw new IOException("Resource not found: " + resPath);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buf = new byte[256];
        int len;
        while ((len = is.read(buf)) != -1) baos.write(buf, 0, len);
        is.close();
        byte[] data = baos.toByteArray();

        // BOM 偵測
        String enc = "UTF-8"; // 預設
        if (data.length >= 2) {
            if (data[0] == (byte)0xFE && data[1] == (byte)0xFF) enc = "UTF-16BE";
            else if (data[0] == (byte)0xFF && data[1] == (byte)0xFE) enc = "UTF-16LE";
            else if (data.length >= 3 && data[0]==(byte)0xEF && data[1]==(byte)0xBB && data[2]==(byte)0xBF) enc = "UTF-8";
        }
        // 去除 BOM
        int bomLen = (enc.startsWith("UTF-16")) ? 2 : (enc.equals("UTF-8") ? 3 : 0);
        if (data.length > bomLen) {
            byte[] content = new byte[data.length - bomLen];
            System.arraycopy(data, bomLen, content, 0, content.length);
            return new String(content, enc);
        }
        return "";
    }
}

二、MIDP 3.0 / Java ME 8 (MeeGo/嵌入式) 新增支援

特性MIDP 2.0MIDP 3.0 / Java ME 8
標準編碼UTF-8, ISO-8859-1 (其餘視實作)強制支援:UTF-8, UTF-16BE, UTF-16LE, US-ASCII, ISO-8859-1
BOM 處理無標準InputStreamReader 自動識別 BOM
資源檔編碼手動指定Class.getResourceAsStream 可搭配 InputStreamReader(IS, "UTF-8")
JAD/ManifestUTF-8 建議強制 UTF-8,且支援 MIDlet-Description- 多語系

若目標平台包含 Java ME 8 (如 Nokia Asha 501、部分嵌入式模組),可大幅簡化編碼處理邏輯。

三、Kotlin / Scala 移植提示

  • Kotlin String(byteArray, Charset) / string.toByteArray(Charset) 對應 Java new String(bytes, enc) / s.getBytes(enc)。
  • Kotlin Charset.forName("GB2312") 會拋 IllegalArgumentException 而非 UnsupportedEncodingException,捕獲時需注意。
  • Scala 同 Java API,但建議用 scala.io.Codec 隱式參數簡化調用。
  • ProGuard/R8 混淆時,保留所有反射用到的編碼名稱字串常量:-keepclassmembers class * { static final java.lang.String *; }。

四、實戰檢查清單 (部署前必驗)

項目驗證方法Through 標準
JAD 檔案編碼Notepad++ → 編碼欄位顯示 UTF-8 無 BOM✅
OTA 下載 Content-Type抓包檢查 charset=UTF-8✅
資源檔 BOM十六進位編輯器確認前 2/3 bytes✅
RMS 讀寫編碼一致單元測試:寫入 → 讀出 → 比對原字串✅
HTTP 請求參數編碼中文參數 URLEncoder.encode(UTF-8)✅
HTTP 回應標頭 charset伺服器回應 Content-Type: application/json; charset=UTF-8✅
裝置不支援編碼降級模擬器關閉 GB2312 測試降級邏輯✅

五、常見異常對應表

異常典型原因修正
UnsupportedEncodingException編碼名稱拼錯 / 裝置真不支援用 EncodingUtil.isSupported() 運行期偵測並降級
IllegalArgumentException (Kotlin)同左捕獲 IllegalArgumentException 而非 UnsupportedEncodingException
亂碼但無異常編碼不匹配 (GB2312 當 UTF-8 解)印出 byte[] 十六進位,對照編碼表確認
截斷/問號DBCS 奇數位元組截斷 / 字型缺字確保 byte[] 長度為偶數;換支援字型或位圖字體

結語

中文編碼問題本質是「協議雙方約定不一致」。建立 編碼偵測 → 統一內部 Unicode (String) → 目標編碼輸出 的標準化管線,配合 EncodingUtil 等工具類封裝平台差異,即可在從 MIDP 1.0 到 Java ME 8 的全版本譜系上實現「零亂碼」交付。記住:**UTF-8 是通用橋樑,JAD/HTTP/XML 強制 UTF-8,本地儲存視空間選 GB2312/Big5,運行期偵測裝置能力優雅降級**。

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