在介绍字符集以前,咱们先了解下为何要有字符集?java
咱们在计算机屏幕上看到的是实体化的文字,而在计算机存储介质中存放的实际是二进制的比特流。那么在这二者之间的转换规则就须要一个统一的标准,不然把咱们的U盘插到老板的电脑上,文档就乱码了;小伙伴QQ上传过来的文件,在咱们本地打开又乱码了。因而为了实现转换标准,各类字符集标准就出现了。数据库
什么是字符集?数组
简单的说字符集就规定了某个文字对应的二进制数字存放方式(编码)和某串二进制数值表明了哪一个文字(解码)的转换关系。浏览器
那么为何会有那么多字符集标准呢?markdown
这个问题实际很是容易回答。问问本身为何咱们的插头拿到英国就不能用了呢?为何显示器同时有DVI,VGA,HDMI,DP这么多接口呢?不少规范和标准在最初制定时并不会意识到这将会是之后全球普适的准则,或者处于组织自己利益就想从本质上区别于现有标准。因而,就产生了那么多具备相同效果但又不相互兼容的标准了。网络
字符集只是一个规则集合的名字,对应到真实生活中,字符集就是对某种语言的称呼。测试
例如:英语,汉语,日语。对于一个字符集来讲要正确编码转码一个字符须要三个关键元素:字库表(character repertoire)、编码字符集(coded character set)、字符编码(character encoding form)。其中字库表是一个至关于全部可读或者可显示字符的数据库,字库表决定了整个字符集可以展示表示的全部字符的范围。编码字符集,即用一个编码值code point来表示一个字符在字库中的位置。字符编码,将编码字符集和实际存储数值之间的转换关系。通常来讲都会直接将code point的值做为编码后的值直接存储。例如在ASCII中A在表中排第65位,而编码后A的数值是0100 0001也即十进制的65的二进制转换结果。网站
ASCII码是7位编码,编码范围是0x00-0x7F。ASCII字符集包括英文字母、阿拉伯数字和标点符号等字符。其中0x00-0x20和0x7F共33个控制字符。编码
只支持ASCII码的系统会忽略每一个字节的最高位,只认为低7位是有效位。HZ字符编码就是早期为了在只支持7位ASCII系统中传输中文而设计的编码。早期不少邮件系统也只支持ASCII编码,为了传输中文邮件必须使用BASE64或者其余编码方式。插件
GB2312是基于区位码设计的,区位码把编码表分为94个区,每一个区对应94个位,每一个字符的区号和位号组合起来就是该汉字的区位码。区位码通常 用10进制数来表示,如1601就表示16区1位,对应的字符是“啊”。在区位码的区号和位号上分别加上0xA0就获得了GB2312编码。
区位码中01-09区是符号、数字区,16-87区是汉字区,10-15和88-94是未定义的空白区。它将收录的汉字分红两级:第一级是经常使用汉字计 3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次经常使用汉字计3008个,置于56-87区,按部首/笔画顺序排列。一级汉字 是按照拼音排序的,这个就能够获得某个拼音在一级汉字区位中的范围,不少根据汉字能够获得拼音的程序就是根据这个原理编写的。
GB2312字符集中除经常使用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符,未收录繁体中文汉字和一些生僻字。能够用繁体汉字测试某些系统是否是只支持GB2312编码。
GB2312的编码范围是0xA1A1-0x7E7E,去掉未定义的区域以后能够理解为实际编码范围是0xA1A1-0xF7FE。
EUC-CN能够理解为GB2312的别名,和GB2312彻底相同。
区位码更应该认为是字符集的定义,定义了所收录的字符和字符位置,而GB2312及EUC-CN是实际计算机环境中支持这种字符集的编码。HZ和ISO- 2022-CN是对应区位码字符集的另外两种编码,都是用7位编码空间来支持汉字。区位码和GB2312编码的关系有点像 Unicode和UTF-8。
GBK编码是GB2312编码的超集,向下彻底兼容GB2312,同时GBK收录了Unicode基本多文种平面中的全部CJK汉字。同 GB2312同样,GBK也支持希腊字母、日文假名字母、俄语字母等字符,但不支持韩语中的表音字符(非汉字字符)。GBK还收录了GB2312不包含的 汉字部首符号、竖排标点符号等字符。
GBK的总体编码范围是为0x8140-0xFEFE,不包括低字节是0×7F的组合。高字节范围是0×81-0xFE,低字节范围是0x40-7E和0x80-0xFE。
低字节是0x40-0x7E的GBK字符有必定特殊性,由于这些字符占用了ASCII码的位置,这样会给一些系统带来麻烦。
有些系统中用0x40-0x7E中的字符(如“|”)作特殊符号,在定位这些符号时又没有判断这些符号是否是属于某个 GBK字符的低字节,这样就会形成错误判断。在支持GB2312的环境下就不存在这个问题。须要注意的是支持GBK的环境中小于0x80的某个字节未必就 是ASCII符号;另外就是最好选用小于0×40的ASCII符号作一些特殊符号,这样就能够快速定位,且不用担忧是某个汉字的另外一半。Big5编码中也 存在相应问题。
CP936和GBK的有些许差异,绝大多数状况下能够把CP936看成GBK的别名。
每一种语言的不一样的编码页,增长了那些须要支持不一样语言的软件的复杂度。于是人们制定了一个世界标准,叫作unicode。unicode为每一个字符提供 了惟一的特定数值,不论在什么平台上、不论在什么软件中,也不论什么语言。也就是说,它世界上使用的全部字符都列出来,并给每个字符一个惟一特定数值。
Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射。但这还不够,它不能覆盖所有历史上的文字,也不能解决传输的问题 (implantation head-ache’s),尤为在那些基于网络的应用中。已有的软件必须作大量的工做来程序16位的数据。
所以,Unicode用一些基本的保留字符制定了三套编码方式。它们分别是UTF-8,UTF-16和UTF-32。正如名字所示,在UTF-8中, 字符是以8位序列来编码的,用一个或几个字节来表示一个字符。这种方式的最大好处,是UTF-8保留了ASCII字符的编码作为它的一部分,例如,在 UTF-8和ASCII中,“A”的编码都是0x41.
UTF-16和UTF-32分别是Unicode的16位和32位编码方式。考虑到最初的目的,一般说的Unicode就是指UTF-16。在讨论Unicode时,搞清楚哪一种编码方式很是重要。
Unicode Transformation Format-8bit,容许含BOM,但一般不含BOM。是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三 个字节)来编码。UTF-8包含全世界全部国家须要用到的字符,是国际编码,通用性强。UTF-8编码的文字能够在各国支持UTF8字符集的浏览器上显 示。如,若是是UTF8编码,则在外国人的英文IE上也能显示中文,他们无需下载IE的中文语言支持包。
GBK的文字编码是用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含所有中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBD大。
GBK、GB2312等与UTF8之间都必须经过Unicode编码才能相互转换:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
对于一个网站、论坛来讲,若是英文字符较多,则建议使用UTF-8节省空间。不过如今不少论坛的插件通常只支持GBK。 unicode是字符集,ASCII、GB23十二、GBK、GB18030既是字符集也是编码方式,UTF-8只是编码方式。
ISO-8859-1:单字节编码,不能显示中文;
GB2312/GBK:专门表示汉字,双字节编码,
gbk表示简体字和繁体字, gb2312只能表示简体字
unicode:最统一的编码,能够用来表示全部语言的字符,并且是定长双字节编码,不兼容那iso-8859-1,也不兼容任何编码。
Java中经常使用的编码转换
1)getBytes(charset):将字符串以字节方式表示,注意字符串在java内存中老是按unicode编码存储;
2)new String(charset):将字节数组按照charset编码进行组合识别,最后转成unicode存储;
Java中注意问题
1)request请求默认的是编码是iso-8859-1
2)iso-8859-1是java网络传输使用的标准字符集