最近开发了一个在手机上打谱的围棋软件(请到本人新浪博客了解详细介绍:yygo手机围棋),因为要读中文棋谱,所以需要支持中文编码。在诺基亚,索爱,多普达等机器上运行良好,可以打开中文棋谱,并显示正常的中文棋评。但在三星,MOTO,联想等机型上无法打开文件。无论用什么中文编码,包括GB2312,GB18030,GBK,都不行。我的做法是:
try {
reader = new InputStreamReader(fis, "GB2312");
} catch (UnsupportedEncodingException ex) {
showMsg("Unsupported Encoding Exception.");
return;
}
reader = new InputStreamReader(fis, "GB2312");
} catch (UnsupportedEncodingException ex) {
showMsg("Unsupported Encoding Exception.");
return;
}
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;
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();
}
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;
}
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;
}
}
if (b < 0) {
return 256 + b;
} else {
return b;
}
}
}
这样直接用这个InputStreamReader包装InputStream类,其他代码根本不用改变。
测试结果:三星手机上可以打开中文棋谱了。其他手机型号如MOTO,联想,有待进一步确认。但我相信应该同样没问题。
本文出自 “mtiger2k” 博客,请务必保留此出处http://mtiger2k.blog.51cto.com/90475/82801