各种编码之间的关系以及getBytes的使用

编码基础知识参考http://my.oschina.net/chape/blog/201725

我对此作了简单的概括

iso8859-1 (通常叫做Latin-1)

属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列,无法表示中文,比如,字母a的编码为0x61=97

 

GB2312/GBK

汉字的国标码,专门用来表示汉字,是不定长双字节编码,而英文字母和iso8859-1一致(兼容iso8859-1编码)。其中gbk编码能够用来同时表示繁体字和简体字,而gb2312只能表示简体字,gbk是兼容gb2312编码的。即GB2312兼容IOS8859-1,GBK兼容GB2312和ISO8859-1

unicode

这是最统一的编码,可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,即不管是中文还是字母都是两个字节,且不兼容任何编码,所以容易浪费很多空间,不利于传输和存储。相对于iso8859-1编码来说,uniocode编码只是在前面增加了一个0字节,比如字母a为"00 61。

定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode编码来处理的,比如java

UTF

考虑到unicode的不足,产生了utf编码,utf编码兼容iso8859-1编码,同时也可以用来表示所有语言的字符

UTF是不定长编码,每一个字符的长度从1-6个字节不等,自带简单的校验功能,一般来讲,英文字母都是用一个字节表示,而汉字使用三个字节。

在考虑选择编码使用的情况下,如果知道使用的都是中文,那么用GB2312/GBK无疑是最省空间的,如果知道了都是不含中文,可以考虑用ISO8859-1。

但是我们一般网页是既含中文也含英文的,GB2312/GBK是国标码,在中国比较通用,而utf是国际支持的,如果用GB2312/GBK,国外访问国内网站,浏览器不支持自动转码,就会出现乱码。所有建议网页上使用utf编码。

 

关于编码的内部实现不深入研究,这里举个例子

以"中文"两个字为例,经查表可以知道其GB2312编码是"d6d0 cec4",Unicode编码为"4e2d 6587",UTF编码就是"e4b8ad e69687"

java中getBytes(charset)

不指定cahrset集时getBytes()默认采用平台默认的编码集,什么是平台默认的编码集呢?就是.java文件保存的编码

比如我的eclipse里保存.java文件为

测试

     String str="哈哈ha1";
        byte b[]=str.getBytes();
        System.out.println(b.length);

哈占3个字节,哈哈就是6个,ha1各占一个,符合UTF-8的编码

不同的编码之间如果不存在兼容关系,肯定是不能互相转换的,如GBK编码的文字不能用UTF-8显示,但ISO编码的字母能用UTF-8或GB2312/GBK显示,因为UTF跟GB2312/GBK是兼容IS0编码的.

但是如果GBK编码的文字通过UTF编码转回GBK呢?

下面做测试

     String str="哈哈123";
        byte utfByte[]=str.getBytes("UTF-8");
        byte gbkByte[]=str.getBytes("GBK");
        byte isoByte[]=str.getBytes("ISO-8859-1");
        //UTF->GBK->UTF
        String str11=new String(utfByte,"GBK");
        String str12=new String(str11.getBytes("GBK"),"UTF-8");
        System.out.println(str12);
        //UTF->ISO->UTF
        String str21=new String(utfByte,"ISO-8859-1");
        String str22=new String(str21.getBytes("ISO-8859-1"),"UTF-8");
        System.out.println(str22);
        //GBK->UTF->GBK
        String str31=new String(gbkByte,"UTF-8");
        String str32=new String(str31.getBytes("UTF-8"),"GBK");
        System.out.println(str32);
        //GBK->ISO->GBK
        String str41=new String(gbkByte,"ISO8859-1");
        String str42=new String(str41.getBytes("ISO8859-1"),"GBK");
        System.out.println(str42);

结果

结论:

UTF-8编码可以用GB2312/GBK和ISO8859-1解码后编回去

GB2312/GBK编码后只能用ISO8859-1解码后编回去

 

posted on 2016-08-18 11:02  pokid  阅读(731)  评论(0编辑  收藏  举报

导航