LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 847|回复: 0

学习了一下字符编码的相关内容

[复制链接]
发表于 2011-8-17 17:56:27 | 显示全部楼层 |阅读模式
前段时间学习了一下字符编码的相关内容,帖出来说说我自己的理解,希望对大家有帮助。文中链接失效了,原文可以看看我的博客的链接
http://a-shi.org/2011/08/10/charactersetencoding/

编码(encoding)指的是把某种信息表示成某种形式的过程。像我们的语言就是一种编码过程,把信息化成文字,声音等语言要素的过程。这里所谈到的编码是指把语言变成计算机可以识别的信息的过程。这个过程纷繁复杂,再加上中文字符本身的特点(比英语字符表示上要复杂),发展出来了许多标准,如果没有一个较好的模型(简单说就是一个分层次的概念),很容易把人搞头大。比如说光看wikipedia上对GB2312,GBK,GB18030,Big5,USC,Unicode,EUC,EUC-CN,EUC-TW,CP936,CP950,UTF-8,UTF-16,UCS-4,UCS-2等等的名词解释,很难清晰的看到他们之间的关系~~

    分层的概念

上面说了这个所谓的编码(encoding)是指把语言变成计算机可以识别的信息的过程。如果把这里的语言简化成所有的中文字,把计算机可以识别的信息简化成2进制数字。那编码就是找一个把中文字映射成2进制数字的映射的过程。当然实际上这个过程还是要繁杂一些,下文中我想结合中文编码说说我的理解,不当之处见谅。
首先介绍一个分层模型,这个模型在文献Whistler and Davis (2000) 和 Dürst et al (2001)中有详细的说明。原来的模型有5个层次,我觉得取其中的三个层次作介绍就足够我们理解编码了。这三个层次分别为:

一、抽象字符集(Abstract character repertoire ),简称ACR,
二、编码后的字符集(Coded character set),简称CCS,
二、字符编码形式(Character encoding form),简称CEF。这个翻译肯定不够恰当,大家尽量以原文 的意思去理解它。

    ACR是就是指一些字符的集合,里边的字符也没有排序,通俗的说,所有简体中文字符就是一个ACR,所有英文字符也是一个ACR,ACR与GB2312之类的名词之间没有对应,这儿提到只是帮助理解。

    CCS是指某个ACR经过处理编排后的字符集合,它是有规律的(排序的),像ASCII码表,中文的区位码表。例如GB2312标准就是定义了这样一个CCS,它里边的中文字符有自己的对应的称为码点(codepoint)的东西和它对应,Codepoin是一个整数。比如中文字“啊”的区位码(准确地说是GB2312的区位码)是整数"1601",这里的1601就是一个codepoint。而ASCII码表里大写字母A的codepoint就是对应的整数十六进制的0×41。
    CEF可以理解为把codepoint映射为码元(code unit)的一种方法。code unit就是计算机所能读懂的信息(2进制码),通常它的长度就是字节(8-bit)的整数倍。比如EUC-CN就是一种CEF,它把GB2312中的codepoint映射成为2进制码。比如它把GB2312中的中文字“啊”的codepoint"1601"映射成"0xB0A1"。

有了这个分层概念,对理解编码就很有用了。

    简体中文字符集和编码

现在就可以介绍中文编码标准,比较有名的是GB2312,确切的说是GB2312-80,GB是“国标”的缩写,80指1980年。这个标准中涉及了CCS,但是并没有涉及到CEF。就是说它只是一个有序的字符集(实际上就是GB2312那张区位码表,它收录了6763个汉字),没有定义它是如何编码的。通常GB2312由EUC-CN来编码(下文会说到EUC-CN),另外GB2312也可以由HZ等编码方式编码。因此一个字符集可以被多种编码方式编码。其实一种编码也可以编码多种字符集,比如ISO-2022-CN可以编码GB2312,也可以同时编码CNS 11643(CNS 11643是台湾的一个繁体字符集标准)。
继续说中文字符集方面的事。GB2312之后又发展出了GBK(但它不是国家标准),K是“扩展”的缩写,它是对GB2312的扩展,它比GB2312-80多收录了更多的字符,确切的说它收录了GB 13000.1-93标准中的所有字符,即收录大陆、台湾、日本及韩国通用字符集的汉字,总共有20,902个。说到GBK,就不得不提CP936,是微软制定的字码表(CodePage),它和GBK几乎一样。实际当中它们相互通用,比如在IANA上的针对GBK的说明中,就指明GBK的别名是CP936,或者MS936,再或者windows-936。但是GBK它算是CCS还是CEF,或者两者都有呢?我没有找到明确的出处说明它是CCS还是CEF。另外CodePage这个词也需要说明一下,严格的来说,在分层模型里,CodePage只涉及到CCS,但是在实际的使用中,它经常包含了CCS和CEF。比如说微软的CP936既指明了它的字符集(CCS)是GBK,又指明了它是怎么编码的,即涉及了CEF。而实际的情况是,很多时候,大家也不太区分GBK和CP936,把GBK直接当作一种编码格式,这样GBK似乎又指定了字符集,又指定了编码方式。GBK的编码方式也是对GB2312最常用的编码方式EUC-CN的扩展。甚至在实际情况里,比如firefox的字符编码菜单中,就直接把GB2312也当成一种编码方式(CEF),其实这里确切的应该是EUC-CN这种编码方式。接着说中文编码,再之后就又发展出了GB18030。GB18030是GB2312和GBK的升级版,它也是兼容前面两个标准的。GB18030这个标准不仅涉及CCS也涉及到CEF。而且它额外的定义了一个从GB18030字符集到Unicode字符集(Unicode详见下文)的映射。我们通常说GB18030这个词的时候,既包含了这是一个字符集(CCS)的含义,又包含了了它是一个种编码方式(CEF)的含义。因此从CCS方面看,它定义了一个比GBK所定义的字符集更广泛的一个字符集:简直是一个巨型字符集–它比Unicode的字符集(见下)还大,关于它的更多讨论可以参看wiki的GB18030。另外从CEF方面看,GB18030又定义了它自己的编码方式,它是一种变长编码方式,这点有点像UTF-8,但是它又需要兼容GBK和GB2312的编码方式,因此又会有EUC-CN的影子。因为GB18030出现在2000年,这个时候Unicode也已经形成,下文会提到它们之间相互影响的地方。

    Unicode和ISO 10646

另外编码中的一个大事就是Unicode标准的出现。Unicode一个大一统标准,它的设计者希望把人类文明里所有的字符都包含在里边,以结束当时各个字符标准各自为战的局面。它不仅涉及CCS也同时涉及CEF。不过当Unicode的组织者开始制订这个标准时,另外一个组织ISO也在做同样的事,它们的标准即ISO 10646。他们最后达成协议,在某些方面达成一致,比如它们在CCS层面上是统一,一个组织要修改字符集的内容的时候需要经过另外一个组织的同意。Unicode的字符集也没有特殊的其它名字,通常也没有对它做区分,我想直接称它为Unicode字符集也无所谓。ISO 10646标准的字符集有一个名字,称为UCS(Universal Character Set)。实际上因为它们两个字符集基本保持一致(也有细微的差别,具体可以参看参考2),所以也就没有必要做区分,通常称为UCS。但是这两个标准在CEF层面上有各自的实现方案:UTF-16,UTF-8,UTF-32就是几种不同的Unicode标准的编码方式(CEF),UCS-2,UCS-4即ISO 10646标准的几种编码方式。其中UTF-32和UCS-4几乎也是一样的,UTF-16和UCS-2又是几乎一样的(确切的说UCS-2是UTF-16的子集,它们在BMP上是完全一样的,具体可以参看参考2。)
因为Unicode是一个大一统标准,因此它也包含对中文的内容。它的字符集中也当然包含了“全部”的中文字符(全部有些不确切,因为这些标准都是在发展中的,新的字也会出现)。因此UTF-8之类的编码方式也是当然支持中文编码的。这样看来GB18030这个标准与Unicode标准有很多交叉的地方,上文提到GB18030标准发布时还定义了一个GB18030字符集与USC之间的双向映射表(确切地说这个映射是关于GB18030字符集的CodePoint到Unicode的CodePoint之间的映射),这样就提供了一种处理GB18030字符编码的方案,先把GB18030的字符通过这个映射表映射成Unicode的字符,再通过UTF-8之类的Unicode编码方式对它编码(引自这里)。这么做我想很大原因应该是GB18030的编码方式有些复杂,这样做可以利用已有的东西。当然GB18030也是可以通过它自身定义的编码来编码的。

    其它

最后说说其它常见的编码。EUC-CN就是一个CEF,它只是一种编码方式,没有涉及到CCS。它的作用就是把GB2312(确切的说是把GB2312的codepoint)映射成相应的码元(Code Unit)。在wiki上的GB2312里,有对EUC-CN的介绍。这种编码可以兼容ASCII编码。另外上文提到过HZ编码,wiki里提到它也是一种编码方式,只涉及到CEF。HZ经常用在USENET上。另外ISO 2022也是一种标准,它的子集ISO 2022-CN就是用来编码GB2312的。而繁体中文方面,Big5是常见的一个标准。它应该是像GBK一样的东西,但是对于繁体中文字符集了解不多,因此我也不展开了。下图简要的就上面所提到名称做了一个分类:
(我这边上传不了附件,可以看看我的博客原文)

    参考

另外插一句,对于处理东亚字符方面的内容,有专门的一本书,称为《CJKV Information Processing》,由Ken Lunde(小林剑)这位丹麦裔的美国人所写。他好像在Adobe,而Adobe是Unicode委员会的最核心成员之一,可见Adobe在这个领域的地位。另外下面的三篇文章我觉得也很有参考价值:

    character set encoding basics
    Understanding Unicode
    Ken Lunde的书的一样章
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表