UTF-8编码与GBK编码之间的转换

.先看一段代码

下面一段代码,将字符串在GBKUTF-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-0xFE160-254

GBK

0x81-0xFE129-254

0x40-0xFE64-254

Big5

0x81-0xFE129-255

0x40-0x7E64-126

0xA10xFE161-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个字节未能找到,显示为?,第56个字节正常输出都为?

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23071790/viewspace-710925/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/23071790/viewspace-710925/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值