各种编码之间的关系以及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解码后编回去