站长资讯网
最全最丰富的资讯网站

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,联想,有待进一步确认。但我相信应该同样没问题。

赞(0)
分享到: 更多 (0)

网站地图   沪ICP备18035694号-2    沪公网安备31011702889846号