一.先看一段代码
下面一段代码,将字符串在GBK与UTF-8之间进行两次转换,第一次生成乱码(UTF-8的字节码用GBK解析),第二次反推这个过程,应该会生成正确的字符串.
但是有些中文字却变成了'???'一类的乱码.只是其中的一些...
private static void print(byte[] bs){
for(byte b:bs)
System.out.print(Integer.toHexString(b).replace("ff","")+" ");
System.out.println();
}
public static void main(String[] args) throws UnsupportedEncodingException {
String utf8="UTF-8";
String gbk="GBK";
String source="可怜";
byte[] sourcebyte=source.getBytes(utf8);
//将字符串转换成UTF-8编码
System.out.println(source);
//打印原字符串
print(sourcebyte);
//================================================
String temp=new String(sourcebyte,gbk);
//使用字符串生成的UTF-8编码生成GBK编码字符串
System.out.println(temp);
//打印结果乱码,意料之中,因为UTF-8中文3字节,而GBK中文大多为双字节,能匹配成功就非乱码,否则使用??替代
//================================================
byte[] targetbyte=temp.getBytes(gbk);
String target=new String(targetbyte,utf8);
System.out.println(target);
//打印最终字符串
print(targetbyte);
}
上面的代码会打印出:
可怜
e5 8f af e6 80 9c
鍙???
可???
e5 8f af e6 3f 3f
二.结果解析
1. 程序中使用了UTF-8 —》GBK —》UTF-8,整个是一个转换和逆转换的过程,按照原先的设想,应该打印出原来的输入值“可怜”,而结果却出现了乱码,中间这个转换的具体细节是什么样的呢?
2. 先使用UTF-8,将字符串转换成字节形式,UTF-8在中文状态下为3字节编码,而两个汉字是6个字节。
3. 将生成的UTF-8字节使用GBK编码转换成字符串,GBK在中文状态下为2字节编码,如果能匹配,正好3个汉字,看一下GBK编码范围:
名称 | 第一字节 | 第二字节 |
GB2312 | 0xB0-0xF7(176-247) | 0xA0-0xFE(160-254) |
GBK | 0x81-0xFE(129-254) | 0x40-0xFE(64-254) |
Big5 | 0x81-0xFE(129-255) | 0x40-0x7E(64-126) 0xA1-0xFE(161-254) |
编码1~2: e5 8f 高字节位符合,低字节位也符合,打印结果:鍙
编码3~4: af e6 高字节位符合,低字节位也符合,打印结果:(空格)
编码5~6: 80 9c 高字节位不符合,低字节位符合,未能找到结果,以??替代
4. 使用GBK,将字符串转换成字节形式,前4个字节因为能在GBK中找到,所以原样输出了,而最后两个字节80 9c无法找到,被替换成了??,所以被转换成了字节3f 3f(3f十进制63,即?的编码)。
5. 最后再次使用UTF-8编码将逆向转换回来的字节转换成字符串时,前3个字节可以正常输出为汉字,而第4个字节未能找到,显示为?,第5、6个字节正常输出都为?
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23071790/viewspace-710925/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/23071790/viewspace-710925/