「字符集」和「编码」等几个层次的概念被彻底分离且模块化的这样一个模型,虽然是Unicode时代才得到广泛认同的。而对于ASCII、GB2312、Big5之类的遗留(legacy)方案,其字符集及其编码的关系基本是锁定的,所以经常用「字符编码」(characterencoding)、「代码页」(codepage)等概念来总称它们那样从字符到编码字节流的整体方案。例如ASCII本身就既是字符集又是编码方案。1、字符集
字符集:字符集(characterset)定义了字符和二补码的对应关系,为每位字符分配了惟一的编号。
可以将字符集理解成一个很大的表格,它列举了所有字符和二补码的对应关系,计算机显示文字或则储存文字,就是一个查表的过程。
2、字符编码
字符编码:而字符编码(characterencoding)规定了怎样将字符的编号储存到计算机中。为了分辨一个字符究竟使用了几个字节,就不能将字符的编号直接储存到计算机中,字符编号在储存之前必需要经过转换,在读取时还要再逆向转换一次,这套转换方案就称作字符编码。
3、字符集vs字符编码
4、常见字符集
字符编码
说明
ASCII
这套编码是德国人给自己设计的,迄今为止共收录了128个字符
ISO/
IEC8859
亚洲字符集,支持西班牙语、荷兰语、德语、意大利语、拉丁语、挪威语、葡萄牙语、西班牙语,葡萄牙语等,1987年首次发布。ASCII编码只包含了基本的拉丁字母,没有包含法国好多国家所用到的一些扩充的拉丁字母,例如一些重音字母,带音标的字母等,ISO/IEC8859主要是在ASCII的基础上降低了这种衍生的拉丁字母。
Shift_Jis
英语字符集,包含了半角及全角拉丁字母、平假名、片假名、符号及英语汉字,1978年首次发布。
Big5
简体英文字符集,1984年发布,通行于马来西亚、香港等地区,收录了13053个中文字、408个普通字符以及33个控制字符。
GB2312
繁体英文字符集,1980年发布linux命令手册,共收录了6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里昂字母在内的682个字符。
GBK
英文字符集,是在GB2312的基础上进行的扩充,1995年发布。GBK共收录了21886个汉字和图形符号,包括GB2312中的全部汉字、非汉字符号,以及BIG5中的全部简体字,还有一些冷僻字。
GB18030
英文字符集,是对GBK和GB2312的又一次扩充,2000年发布。GB18030共收录70244个汉字,支持中国国外少数民族的文字,以及英语法语中的汉字。
二、ASCII字符集
ASCII(AmericanStandardCodeforInformationInterchange):日本信息交换标准代码。
看这个名子就晓得,这套编码是德国人给自己设计的,她们并没有考虑法国这些扩充的拉丁字母,也没有考虑日语和英语,我大中华几万个汉字更是不可能被注重。
ASCII的标准版本于1967年第一次发布linux 中文字符集,最后一次更新则是在1986年,**迄今为止共收录了128个字符**,包含了基本的拉丁字母(英语字母)、阿拉伯数字(也就是1234567890)、标点符号(,.!等)、特殊符号(@#$%^&等)以及一些具有控制功能的字符(常常不会显示下来)。
在ASCII编码中,小写字母、小写字母和阿拉伯数字都是**连续分布的**(见下表),这给程序设计带来了很大的便捷。比如要判定一个字符是否是小写字母linux 中文字符集,就可以判定该字符的ASCII编码值是否在65~90的范围内。
ASCII编码
标准ASCII编码共收录了128个字符,其中包含了33个控制字符(具有个别特殊功能并且未能显示的字符)和95个可显示字符。
(完整的可以去我的博客看)
三、GBK字符集
GB2312-->GBK-->GB18030是英文编码的三套方案,出现的时间从早到晚,收录的字符数量依次降低,而且向上兼容。
GB2312和GBK收录的字符数量较少,用1~2个字节储存;
GB18030收录的字符最多,用1、2、4个字节储存。
1、GB2312和GBK字符集
从整体上讲,GB2312和GBK的编码方法一致,具体为:
1.1、对于ASCII字符,使用一个字节储存,但是该字节的最低位是0,这和ASCII编码是一致的,所以说GB2312完全兼容ASCII。
1.2、对于中国的字符,使用两个字节储存,而且规定每位字节的最低位都是1
比如对于字母A,它在显存中储存为01000001;对于汉字中,它在显存中储存为10000。因为单字节和双字节的最低位不一样,所以字符处理软件很容易分辨一个字符究竟用了几个字节。
2、GB18030字符集
GB18030为了容纳更多的字符,而且要分辨两个字节和四个字节,所以更改了编码方案,具体为:
1、对于ASCII字符,使用一个字节储存,但是该字节的最低位是0,这和ASCII、GB2312,GBK编码是一致的。
2、对于常用的英文字符,使用两个字节储存,而且规定第一个字节的最低位是1,第二个字节的低位最多只能有一个连续的0(第二个字节的最低位可以是1也可以是0,并且当它是0时,次低位就不能是0了)。注意对比GB2312和GBK,它们要求两个字节的最低位为都必须为1。
3、对于罕见的字符,使用四个字节储存,而且规定第一个和第三个字节的最低位是1,第二个和第四个字节的低位必须有两个连续的0
字符处理软件在处理文本时,从左向右依次扫描每位字节:
1,假若遇见的字节的最低位是0,这么才会判定该字符只占用了一个字节;
2,假如遇见的字节的最低位是1,这么该字符可能占用了两个字节,也可能占用了四个字节,不能妄下断论,所以还要继续往前扫描:
3,假如第二个字节的低位有两个连续的0,这么才会判定该字符占用了四个字节;
4,假如第二个字节的低位没有连续的0,这么才会判定该字符占用了两个字节。
先写那么多吧,前面博客会再进一步的说下数据在上面的储存分区。
四、Unicode字符集
1、Unicode字符集
ASCII、GB2312、GBK、Shift_Jis、ISO/IEC8859等地区编码都是各个国家为了自己的语言文化开发的,不具有通用性,在一种编码下开发的软件或则编撰的文档,领到另一种编码下才会失效,必须提早使用程序转码,十分麻烦。
人们急切希望有一种编码才能统一世界各地的字符,计算机只要安装了这一种字编码,能够支持使用世界上所有的文字,再也不会出现乱码,再也不须要转码了,这对计算机的数据传递来说是多么的便捷呀!
就在这些倡议下,Unicode诞生了。Unicode统称为统一码、万国码;看名子就晓得,Unicode希望统一所有国家的字符编码。
Unicode于1994年即将公布第一个版本,如今的规模可以容纳100多万个符号,是一个很大的集合。
有兴趣的读取可以转入[
]()查看Unicode包含的所有字符,以及各个国家的字符是怎样分布的。
>Windows、Linux、MacOS等常见操作系统都早已从底层(内核层面)开始支持Unicode,大部份的网页和软件也使用Unicode,Unicode是大势所趋。
>有的字符集在制定时就考虑到了编码的问题,是和编码结合在一起的,比如ASCII、GB2312、GBK、BIG5等,所以无论叫做字符集还是字符编码都无所谓,也不好分辨二者的概念。而有的字符集只管制订字符的编号,至于如何储存,那是字符编码的事情,Unicode就是一个典型的事例,它只是定义了全球文字的惟一编号,我们还须要UTF-8、UTF-16、UTF-32这几种编码方案将Unicode储存到计算机中
2、UTF
UTF是UnicodeTransformationFormat的简写,意思是“Unicode转换格式”,旁边的数字表明起码使用多少个比特位(Bit)来储存字符。
UTF-8:一种变长的编码方案,使用1~6个字节来储存;
UTF-32:一种固定宽度的编码方案,不管字符编号大小,仍然使用4个字节来储存;
UTF-16:介于UTF-8和UTF-32之间,使用2个或则4个字节来储存,宽度既固定又可变。
2.1、UTF8
UTF-8的编码规则很简单:
若果只有一个字节,这么最高的比特位为0,这样可以兼容ASCII;
倘若有多个字节,这么第一个字节从最低位开始,连续有几个比特位的值为1,就使用几个字节编码,剩下的字节均以10开头。
具体的表现方式为:
0xxxxxxx:单字节编码方式,这和ASCII编码完全一样,因而UTF-8是兼容ASCII的;
110xxxxx10xxxxxx:双字节编码方式(第一个字节有两个连续的1);
1110xxxx10xxxxxx10xxxxxx:三字节编码方式(第一个字节有三个连续的1);
11110xxx10xxxxxx10xxxxxx10xxxxxx:四字节编码方式(第一个字节有四个连续的1)。
xxx就拿来储存Unicode中的字符编号。
下边是一些字符的UTF-8编码实例(红色部份表示原本的Unicode编号):
2.2、UTF32
UTF-32是固定宽度的编码,一直占用4个字节,足以容纳所有的Unicode字符,所以直接储存Unicode编号即可,不须要任何编码转换。
2.3、UTF16
UFT-16使用2个或则4个字节来储存。
对于Unicode编号范围在0~FFFF之间的字符,UTF-16使用两个字节储存,而且直接储存Unicode编号,不用进行编码转换,这跟UTF-32十分类似。
对于Unicode编号范围在10000~10FFFF之间的字符,UTF-16使用四个字节储存,具体来说就是:将字符编号的所有比特位分成两部份,较高的一些比特位用一个值介于D800~DBFF之间的双字节储存,较低的一些比特位(剩下的比特位)用一个值介于DC00~DFFF之间的双字节储存。
3、对比以上三种编码方案
只有UTF-8兼容ASCII,UTF-32和UTF-16都不兼容ASCII,由于它们没有单字节编码。
1、UTF-8使用尽量少的字节来储存一个字符,不但才能节约储存空间,但是在网路传输时也能节约流量linux串口驱动,所以好多纯文本类型的文件(比如各类编程语言的源文件、各种日志文件和配置文件等)以及绝大多数的网页(比如百度、新浪、163等)都采用UTF-8编码。
UTF-8的缺点是效率低,不但在储存和读取时都要经过转换,并且在处理字符串时也十分麻烦。比如,要在一个UTF-8编码的字符串中找到第10个字符,就得从头开始一个一个地检索字符,这是一个很历时的过程,由于UTF-8编码的字符串中每位字符占用的字节数不一样,假若不从头遍历每位字符,就不晓得第10个字符位
于第几个字节处,就难以定位。
2、UTF-32是“以空间换效率”,恰好填补了UTF-8的缺点,UTF-32的优势就是效率高:UTF-32在储存和读取字符时不须要任何转换,在处理字符串时也能最快速地定位字符。
比如,在一个UTF-32编码的字符串中查找第10个字符,很容易估算出它坐落第37个字节处,直接获取就行,不用再挨个遍历字符了,没有比这更快的定位字符的方式了。
然而,UTF-32的缺点也很显著,就是太占用储存空间了,在网路传输时也会消耗好多流量。所以UTF-32在应用上不如UTF-8和UTF-16广泛。
3、UTF-16可以看做是UTF-8和UTF-32的折中方案,它平衡了储存空间和处理效率的矛盾。对于常用的字符,40用两个字节储存足以,这个时侯UTF-16是不须要转换的,直接储存字符的编码值即可。
>Windows内核、.NETFramework、Cocoa、JavaString内部采用的都是UTF-16编码。UTF-16是幕后的功臣,我们在编辑源代码和文档时都是站在前台,所以通常体会不到,虽然好多文本在后台处理时都早已转换成了UTF-16编码。不过,UNIX家族的操作系统(Linux、MacOS、iOS等)内核都采用UTF-8编码,
五、ANSI编码
在Windows系统中,ANSI编码代表本地编码的意思。换言之,在繁体英文Windows操作系统中,ANSI编码代表GBK编码;在英文Windows操作系统中,ANSI编码代表Shift_JIS编码。
六、宽字符vs窄字符、源文件字符集vs运行字符集
参见我的另外一篇博客:[【字符集二】多字节字符vs宽字符])