天天看点

编码史记字符编码的故事

昨天听了一个同事的编码讲座,很精彩。想起了要写这个文章分享一下各种编码是如何产生的。

字符是什么?就是有意义的图形,比如a,中等。在不同的国家代表不同的意思。

但是在计算机世界中只有0和1,好了,如何用0和1将这些字符表示出来呢?这就是编码存在的意义。

编码一点也不高深,就是一个计算机的01和字符ab的简单映射。

欧洲人出场了。欧洲是有好多个国家的,他们的每个国家也都有自己的文字,比如拉丁文,希腊文等。怎么办呢?于是想到,你美国人指定的ascii码表里面不是只有127个字符吗,后面128-255的字符不是说待定吗,好吧,我们就不客气了。于是欧洲人就将各种奇怪的语言塞入127后面的字符中,形成了一系列的iso 8859字符集。比如希腊文塞入ascii,就形成了iso/iec 8859-7,西欧语种塞入ascii就形成了iso/iec 8859-1,iso/iec 8859-1也叫做latin-1。(对,就是mysql里面经常见到的编码)

iso/iec 8859-1 (latin-1) - 西欧语言 

iso/iec 8859-2 (latin-2) - 中欧语言 

iso/iec 8859-3 (latin-3) - 南欧语言。世界语也可用此字符集显示。 

iso/iec 8859-4 (latin-4) - 北欧语言 

iso/iec 8859-5 (cyrillic) - 斯拉夫语言 

iso/iec 8859-6 (arabic) - 阿拉伯语 

iso/iec 8859-7 (greek) - 希腊语 

iso/iec 8859-8 (hebrew) - 希伯来语(视觉顺序) 

iso 8859-8-i - 希伯来语(逻辑顺序) 

iso/iec 8859-9(latin-5 或 turkish)- 它把latin-1的冰岛语字母换走,加入土耳其语字母。 

iso/iec 8859-10(latin-6 或 nordic)- 北日耳曼语支,用来代替latin-4。 

iso/iec 8859-11 (thai) - 泰语,从泰国的 tis620 标准字集演化而来。 

iso/iec 8859-13(latin-7 或 baltic rim)- 波罗的语族 

iso/iec 8859-14(latin-8 或 celtic)- 凯尔特语族 

iso/iec 8859-15 (latin-9) - 西欧语言,加入latin-1欠缺的芬兰语字母和大写法语重音字母,以及欧元(€)符号。 

iso/iec 8859-16 (latin-10) - 东南欧语言。主要供罗马尼亚语使用,并加入欧元符号。 

接着伟大的中国人也开始使用上电脑了。中文可不得了,文字博大精深,字符远远超过了256个。所以我们无法使用ascii的扩展了。怎么办呢? 1981年的时候,国家派一批人来做了这个事情,他们统计出所有的中文大概有6000多个字符(后来证明这些人的水品也是有限,好多字符都没有搜出来,于是就有了多种的中文编码),用两个字节(16bit)来表示,16bit能表示的是65536个字符,太够了。我们将16bit分为前8bit和后8bit 

如果前8bit小于127(英文ascii),那么这个8bit就是表示英文 

如果前8bit大于127,那么这8bit和后面的8bit合起来表示一个中文

gb是啥意思?国标。

好了,后来某些领导发现,他的名字没法编码了,这个问题出来了。6000个汉字还不足以囊括所有中文,国家在1995年又组织了一批人,继续搜罗一些生僻字,一共搜集出了21886个汉字和字符,形成了gbk编码,gbk编码向下兼容gb2312。

k是啥意思?扩展。

再后来发现了,一些满文,蒙古文啥的少数名族的语言没有编辑到gbk中,继续编辑收录,形成了gb18030编码。

big5是什么意思? 

五种中文套装软体:文书处理,资料库,试算表,通讯,绘图。大致的意思是这套编码主要使用于这5个领域

各个国家使用各个国家自己的编码有没有很繁琐?于是大家很期盼有一种统一的编码形式出现。unicode编码出现了。unicode使用的通用的字符集叫做ucs。这个字符集就是一个大的字符空间,每个语种都在这个字符空间内划分一段领域。现在应用的ucs是ucs-2,意思就是不管是英文中文,统一使用两个字节(16bit)来进行字符分配。ucs-2字符集可以表示216(即65536)个字符。已经基本满足世界上所有语言了。如果不够怎么办?已经有预定方案ucs-4(用4个字节表示一个字符)。

切记:utfxx是unicode的具体实现方式。

utf-16是unicode最基本的实现。unicode使用16bit表示一个字符,utf-16就是直接将字符集的映射搬过来而已。

utf-8这种编码是怎么回事呢? 

英文字符,和ascii码一样,占用一个字节 

其他语种,每种语种分配一个模板,这个模板有16bit,24bit,甚至还有32bit的。各个语种根据这个模板,将自己的语言转化成模板要求的编码(utf-8) 

这里演示一个中文字“汉” 

比如中文分到的模板是1110xxxx 10yyyyyy 10zzzzzz 

汉字的unicode编码是0x6c49,二进制是0110 1100 0100 1001 

将这个二进制按照模板的x,y,z顺序插入 

得到11100110 10110001 10001001 就是e6 b1 89 

好了…大家看出这个对中文有什么不好的吗?原先一个中文使用utf-16只需要两个字节,但是使用utf-8却需要3个字节,如果一个网页有1w个中文字,那么我们就需要多传输1w个字节,带宽啊!! 现在就明白了,为什么国内一些网站,比如sina,它的编码规则是使用gbk了吧!

下面再说一下很多编辑器的自动编码匹配的问题。编辑器会检查出你输入的字符是utf-8还是gbk,基本根据的就是这个utf-8模板,如果符合模板,就会判断是utf-8。很多文章说的txt中输入“联通”存为gbk编码再打开会出现乱码就是这个原因导致的。

还有一种ansi是什么呢?windows内核是使用utf-16编写的,但是页面上展示的语言是根据系统设置的“语言”来展示的。ansi就是windows系统根据你设置的语言环境而进行自动变化的一种编码。比如在中文windows系统下,ansi就代表gbk编码,日文操作系统下就代表jis编码。

继续阅读