我們來自五湖四海,不為別的,只因有共同的愛好,為中國互聯網發展出一分力!

JAVA/J2ME中文編碼問題完全解決方案

2012年01月09日18:23 閱讀: 1394 次

標簽: Java, J2ME, 中文編碼

最近開發了一個在手機上打譜的圍棋軟件(請到本人新浪博客了解詳細介紹:yygo手機圍棋),因為要讀中文棋譜,所以需要支持中文編碼。在諾基亞,索愛,多普達等機器上運行良好,可以打開中文棋譜,并顯示正常的中文棋評。但在三星,MOTO,聯想等機型上無法打開文件。無論用什么中文編碼,包括GB2312,GB18030,GBK,都不行。我的做法是:

try {
     reader = new InputStreamReader(fis, "GB2312");
} catch (UnsupportedEncodingException ex) {
     showMsg("Unsupported Encoding Exception.");
     return;
}

后來在GOOGLE上看了一篇文章:Main: J2ME經驗總結之GB2312轉換類Un ...,決定自已處理GB2312字節。但是直接調用HGB2312.gb2utf8,諾基亞上沒問題,在三星手機上還是行不通,顯示亂碼。
str = hgb2312.gb2utf8(str.getBytes());

研究了諾基亞SDK里的InputStreamReader實現后,發現Reader類無非就是按指定的編碼,把字節一個一個提出來分析,按照編碼格式拼裝成一個個char,這個處理方式跟HGB2312里的字節處理原理是一樣的。于是決定自己實現一個InputStreamReader。實際上只要繼承java.io.Reader類,實現兩個方法就行了:

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
public class InputStreamReader extends Reader {
private byte[] map = new byte[15228];
InputStream In;

public InputStreamReader(InputStream inputstream) throws Exception {
  In = inputstream;
  InputStream is = getClass().getResourceAsStream("/gb2u.dat");
  is.read(map);
  is.close();
}

public void close() throws IOException {
  In.close();
}
public int read(char[] ac, int i, int j) throws IOException {
  byte bt;
  byte[] bytes;
  int ret;
  int k = 0;
  while (k < j) {
   int c, h, l, ind;
   bytes = new byte[1];
   ret = In.read(bytes);
   if (ret==-1) break;
  
   bt = bytes[0];
   if (bt >= 0) {
             ac[i+k] = ((char) bt);
         } else {
          bytes = new byte[1];
          ret = In.read(bytes);
          if (ret==-1) break;
          
          h = 256 + bt;
             l = 256 + bytes[0];
             h = h - 0xA0 - 1;
             l = l - 0xA0 - 1;
             if (h < 9) {
                 ind = (h * 94 + l) << 1;
                 c = (byte2Int(map[ind]) << 8 | byte2Int(map[ind + 1]));
                 ac[i+k] = ((char) c);
             } else if (h >= 9 && h <= 14) {
              ac[i+k] = ((char) 0);
             } else if (h > 14) {
                 h -= 6;
                 ind = (h * 94 + l) << 1;
                 c = (byte2Int(map[ind]) << 8 | byte2Int(map[ind + 1]));
                 ac[i+k] = ((char) c);

             } else {
              ac[i+k] = ((char) 0);
             }
         }
   k++;
  }
  return k != 0 ? k : -1;
}
private int byte2Int(byte b) {
  if (b < 0) {
   return 256 + b;
  } else {
   return b;
  }
}
}
其中主要是public int read(char[] ac, int i, int j) 這個方法。

這樣直接用這個InputStreamReader包裝InputStream類,其他代碼根本不用改變。

測試結果:三星手機上可以打開中文棋譜了。其他手機型號如MOTO,聯想,有待進一步確認。但我相信應該同樣沒問題。
分享到: 更多
藍客門戶
©2001-2019 中國藍客聯盟 版權所有.
關于藍客聯盟歷史宗旨章程技術服務聯系我們藍客社區

云南11选5遗漏