[编码]ASCII、GBK、Unicode(万国码)和UTF-8
American   ASCII编码(American Standard Code for Information Interchange,美国信息互换标准代码)
China      gbk编码通称他们叫做 “DBCS“(Double Byte Charecter Set 双字节字符集)
统⼀            Unicode        统⼀码、万国码
       utf-8      互联⽹上使⽤最⼴的⼀种unicode的实现⽅式,为传输⽽设计的编码。特点:变长编码⽅式、统⼀⽆国界
很久很久以前,有⼀⼈,他们决定⽤8个可以开合的晶体管来组合成不同的状态,以表⽰世界上的万物。他们看到8个开关状态是好的,于是他们把这称为”字节“。再后来,他们⼜做了⼀些可以处理这些字节的机器,机器开动了,可以⽤字节来组合出很多状态,状态开始变来变去。他们看到这样是好的,于是它们就这机器称为”计算机“。
开始计算机只在美国⽤。⼋位的字节⼀共可以组合出256(2的8次⽅)种不同的状态。他们把其中的编号从0开始的32种状态分别规定了特殊的⽤途,⼀但终端、打印机遇上约定好的这些字节被传过来时,就要做⼀些约定的动作。遇上0×10, 终端就换⾏,遇上0×07, 终端就向⼈们嘟嘟叫,例好遇上0x1b, 打印机就
打印反⽩的字,或者终端就⽤彩⾊显⽰字母。他们看到这样很好,于是就把这些0×20以下的字节状态称为”控制码”。他们⼜把所有的空格、标点符号、数字、⼤⼩写字母分别⽤连续的字节状态表⽰,⼀直编到了第127号,这样计算机就可以⽤不同字节来存储英语的⽂字了。⼤家看到这样,都感觉很好,于是⼤家都把这个⽅案叫做 ANSI 的”Ascii”编码(American Standard Code for Information Interchange,美国信息互换标准代码)。当时世界上所有的计算机都⽤同样的ASCII⽅案来保存英⽂⽂字。
后来,就像建造巴⽐伦塔⼀样,世界各地的都开始使⽤计算机,但是很多国家⽤的不是英⽂,他们的字母⾥有许多是ASCII⾥没有的,为了可以在计算机保存他们的⽂字,他们决定采⽤ 127号之后的空位来表⽰这些新的字母、符号,还加⼊了很多画表格时需要⽤下到的横线、竖线、交叉等形状,⼀直把序号编到了最后⼀个状态255。从128 到255这⼀页的字符集被称”扩展字符集“。从此之后,贪婪的⼈类再没有新的状态可以⽤了,美帝国主义可能没有想到还有第三世界国家的⼈们也希望可以⽤到计算机吧!
等中国⼈们得到计算机时,已经没有可以利⽤的字节状态来表⽰汉字,况且有6000多个常⽤汉字需要保存呢。但是这难不倒智慧的中国⼈民,我们不客⽓地把那些127号之后的奇异符号们直接取消掉, 规定:⼀个⼩于127的字符的意义与原来相同,但两个⼤于127的字符连在⼀起时,就表⽰⼀个汉字,前⾯的⼀个字节(他称之为⾼字节)从0xA1⽤到 0xF7,后⾯⼀个字节(低字节)从0xA1到0xFE,这样
我们就可以组合出⼤约7000多个简体汉字了。在这些编码⾥,我们还把数学符号、罗马希腊的字母、⽇⽂的假名们都编进去了,连在 ASCII ⾥本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全⾓”字符,⽽原来在127号以下的那些就叫”半⾓”字符了。中国⼈民看到这样很不错,于是就把这种汉字⽅案叫做 “GB2312“。GB2312 是对 ASCII 的中⽂扩展。
但是中国的汉字太多了,我们很快就就发现有许多⼈的⼈名没有办法在这⾥打出来,特别是某些很会⿇烦别⼈的国家领导⼈。于是我们不得不继续把 GB2312 没有⽤到的码位出来⽼实不客⽓地⽤上。后来还是不够⽤,于是⼲脆不再要求低字节⼀定是127号之后的内码,只要第⼀个字节是⼤于127就固定表⽰这是⼀个汉字的开始,不管后⾯跟的是不是扩展字符集⾥的内容。结果扩展之后的编码⽅案被称为 GBK 标准,GBK包括了GB2312 的所有内容,同时⼜增加了近20000个新的汉字(包括繁体字)和符号。后来少数民族也要⽤电脑了,于是我们再扩展,⼜加了⼏千个新的少数民族的字,GBK扩成了 GB18030。从此之后,中华民族的⽂化就可以在计算机时代中传承了。中国的程序员们看到这⼀系列汉字编码的标准是好的,于是通称他们叫做 “DBCS“(Double Byte Charecter Set 双字节字符集)。在DBCS系列标准⾥,最⼤的特点是两字节长的汉字字符和⼀字节长的英⽂字符并存于同⼀套编码⽅案⾥,因此他们写的程序为了⽀持中⽂处理,必须要注意字串⾥的每⼀个字节的值,如果这个值是⼤于127的,那么就认为⼀个双字节字符集⾥的字符出现了。那时候凡是受过加持,会编程的计算机僧侣们都要每天念下⾯这个咒语数百遍: “⼀个汉字算两个英⽂字符!⼀个汉字算两个英⽂字符……”
因为当时各个国家都像中国这样搞出⼀套⾃⼰的编码标准,结果互相之间谁也不懂谁的编码,谁也不⽀持别⼈的编码,连⼤陆和台湾这样只相隔了150海⾥,使⽤着同⼀种语⾔的兄弟地区,也分别采⽤了不同的 DBCS 编码⽅案——当时的中国⼈想让电脑显⽰汉字,就必须装上⼀个”汉字系统”,专门⽤来处理汉字的显⽰、输⼊的问题,但是那个台湾的愚昧封建⼈⼠写的算命程序就必须加装另⼀套⽀持 BIG5 编码的什么”倚天汉字系统”才可以⽤,装错了字符系统,显⽰就会乱了套!这怎么办?⽽且世界民族之林中还有那些⼀时⽤不上电脑的穷苦⼈民,他们的⽂字⼜怎么办?真是计算机的巴⽐伦塔命题啊!
正在这时,⼤天使加百列及时出现了——⼀个叫 ISO (国际标谁化组织)的国际组织决定着⼿解决这个问题。他们采⽤的⽅法很简单:废了所有的地区性编码⽅案,重新搞⼀个包括了地球上所有⽂化、所有字母和符号的编码!他们打算叫它”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode“。
unicode开始制订时,计算机的存储器容量极⼤地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须⽤两个字节,也就是16位来统⼀表⽰所有的字符,对于ASCII⾥的那些“半⾓”字符,unicode包持其原编码不变,只是将其长度由原来的8位扩展为16位,⽽其他⽂化和语⾔的字符则全部重新统⼀编码。由于”半⾓”英⽂符号只需要⽤到低8位,所以其⾼8位永远是0,因此这种⼤⽓的⽅案在保存英⽂⽂本时会多
浪费⼀倍的空间。
这时候,从旧社会⾥⾛过来的程序员开始发现⼀个奇怪的现象:他们的strlen函数靠不住了,⼀个汉字不再是相当于两个字符了,⽽是⼀个!是的,从unicode开始,⽆论是半⾓的英⽂字母,还是全⾓的汉字,它们都是统⼀的”⼀个字符“!同时,也都是统⼀的”两个字节“,请注意”字符”和”字节”两个术语的不同,“字节”是⼀个8位的物理存贮单元,⽽“字符”则是⼀个⽂化相关的符号。在unicode中,⼀个字符就是两个字节。⼀个汉字算两个英⽂字符的时代已经快过去了。
unicode同样也不完美,这⾥就有两个的问题,⼀个是,如何才能区别unicode和ascii?计算机怎么知道三个字节表⽰⼀个符号,⽽不是分别表⽰三个符号呢?第⼆个问题是,我们已经知道,英⽂字母只⽤⼀个字节表⽰就够了,如果unicode统⼀规定,每个符号⽤三个或四个字节表⽰,那么每个英⽂字母前都必然有⼆到三个字节是0,这对于存储空间来说是极⼤的浪费,⽂本⽂件的⼤⼩会因此⼤出⼆三倍,这是难以接受的。
unicode在很长⼀段时间内⽆法推⼴,直到互联⽹的出现,为解决unicode如何在⽹络上传输的问题,于是⾯向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,⽽UTF-16就是每次16个位。UTF-8就是在互联⽹上使⽤最⼴的⼀种unicode的实现⽅式,这是为传输⽽设计的编码,并使编码⽆国界,这样就可以显⽰全世界上所有⽂化的字符了。
UTF-8最⼤的⼀个特点,就是它是⼀种变长的编码⽅式。它可以使⽤1~4个字节表⽰⼀个符号,根据不同的符号⽽变化字节长度,当字符在ASCII 码的范围时,就⽤⼀个字节表⽰,保留了ASCII字符⼀个字节的编码做为它的⼀部分,注意的是unicode⼀个中⽂字符占2个字节,⽽UTF-8⼀个中⽂字符占3个字节)。从unicode到uft-8并不是直接的对应,⽽是要过⼀些算法和规则来转换。
Unicode符号范围 | UTF-8编码⽅式
(⼗六进制) | (⼆进制)
—————————————————————–
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
举⼀个例⼦:It's 知乎⽇报
你看到的unicode字符集是这样的编码表:
I 0049
t 0074
' 0027
s 0073unicode汉字
0020
知 77e5
乎 4e4e
⽇ 65e5
报 62a5
每⼀个字符对应⼀个⼗六进制数字。
计算机只懂⼆进制,因此,严格按照unicode的⽅式(UCS-2),应该这样存储:
I 00000000 01001001
t 00000000 01110100
' 00000000 00100111
s 00000000 01110011
00000000 00100000
知 01110111 11100101
乎 01001110 01001110
⽇ 01100101 11100101
报 01100010 10100101
这个字符串总共占⽤了18个字节,但是对⽐中英⽂的⼆进制码,可以发现,英⽂前9位都是0!浪费啊,浪费硬盘,浪费流量。
怎么办?
UTF。
UTF-8是这样做的:
1. 单字节的字符,字节的第⼀位设为0,对于英语⽂本,UTF-8码只占⽤⼀个字节,和ASCII码完全相同;
2. n个字节的字符(n>1),第⼀个字节的前n位设为1,第n+1位设为0,后⾯字节的前两位都设为10,这n个字节的其余空位填充该字符unicode码,⾼位⽤0补⾜。
这样就形成了如下的UTF-8标记位:
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
... ...
于是,”It's 知乎⽇报“就变成了:
I 01001001
t 01110100
' 00100111
s 01110011
00100000
知 11100111 10011111 10100101
乎 11100100 10111001 10001110
⽇ 11100110 10010111 10100101
报 11100110 10001010 10100101
和上边的⽅案对⽐⼀下,英⽂短了,每个中⽂字符却多⽤了⼀个字节。但是整个字符串只⽤了17个字节,⽐上边的18个短了⼀点点。
下边是课后作业:
请将”It's 知乎⽇报“的GB2312和GBK码(⾃⾏google)转成⼆进制。不考虑历史因素,从技术⾓度解释为什么在unicode和UTF-8⼤⾏其道的同时,GB2312和GBK仍在⼴泛使⽤。
剧透:⼀切都是为了节省你的硬盘和流量。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。