最近又复习了一遍字符编码,常用的链接:
UTF-8概念:
http://www.linuxforum.net/books/UTF-8-Unicode.html
Unicode概念:
http://wiki.ccw.com.cn/Unicode
Unicode编码(0000-0FFF):
http://wiki.ccw.com.cn/Unicode%E7%BC%96%E7%A0%81%E8%A1%A8/0000-0FFF
Java中一般来说String存放的是Unicode编码,
JDK1.5中可以用构造函数:
String(byte[] bytes, int offset, int length, String charsetName)
构造一个新的 String,方法是使用指定的字符集解码字节的指定子数组。
以前有charsetName参数的构造函数过时了.
这次还用到了StringBuffer,它是线程安全的可以修改String的类.
它里边存放的字符也是Unicode编码的,charAt(int index)可以得到索引中存放的Unicode编码的字符,
注意Java里的字符长度与int的长度一样,而不是像C中的char和byte,
当把大于0x80取出来的字符charAt(0)强制转为int时会变成负数,而不是0x80.因此,使用String.getBytes("UTF-8")就会有这样的问题:
charAt(0)是负数,类似于这样:0xFFA1, 本来0xA1转成UTF-8是0xC2 0xA1,现在好了,它把前面的FF也算进来了,于是就转成了另外一个字符.解决方法是charAt(0) & 0xFF
现在读取网络上的字节流,但遇到这样的问题:
流是ISO-8859-1编码的,有这样一串字节: 0xFD 0x71 0x62,使用in.getLine()读取一行,包含上述字节的话,Java会把0xFD 0x71放在一起作为一个char!
于是我就手动将它分开?弄一个StringBuffer,从最后一个字节开始判断,如果 charAt(index) & 0xFF00 > 0,则将低位insert(index, charAt(index) & 0xFF),然后setCharAt(index, (charAt(index) & 0xFF00)>>8)
这样就好了吗?No!你会发现,0xFD 0x71放到String里再用charAt(index)读出来就不是0xFD 0x71了!,那怎么办?
1) 让iLow=chrTemp的低位, iHigh=chrTemp的高位
2) 用new String(new byte[]{(byte) iHigh, (byte) iLow}, 0, 2, "Unicode");构造出一个新的strTemp
3) strTemp.getBytes()得到两个byte,这两个byte才是0xFD, 0x71
int iLow = chrTemp & 0xFF;
int iHigh = (chrTemp & 0xFF00) >> 8;
byte[] aryByte = new byte[]{(byte) iHigh, (byte) iLow};
String strTempUnicode = null;
try {
strTempUnicode = new String(aryByte, 0, 2, "Unicode");
byte[] aryByteResult = strTempUnicode.getBytes();
sb.insert(j+1, (char) (aryByteResult[1] & 0xFF));
sb.setCharAt(j, (char) (aryByteResult[0] & 0xFF));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}