My Profile Photo

wlnirvana


Youth is not a time of life, it is a state of mind.


汉字编码笔记(1)

这两天搞LaTeX,在Scientific Workplace和LyX之间、Windows和Linux之间换来换去,弄得焦头烂额。后来发现,中间很多问题都是汉字编码的不同造成的。那么汉字编码究竟是怎么一回事呢?

在搞清楚这个问题之前,我们首先得明白,计算机内所有的信息都是以二进制的形式储存的。比如在屏幕上我们可以随心所欲地打出“abc123天气真好”等各种各样的字符,可是计算机不认得这些复杂的字符。在他看来,a不过相当于1100001,1则是110001,等等。经过一定的处理之后,这些二进制串才能转化为我们想要的内容。而将各种字符和二进制串一一对应起来的过程,就是编码。

好了,现在问题出现了,该怎么样对这些字符进行编码呢?比如说我想让数字的编码跟数字本身的大小对应起来,于是我把1编码成1,2编码成10,3编码成11……以此类推,二进制编码和十进制就对应了。可是你不一定想这样编码,你可能觉得字母应该放在前头,所以你把a编码成1,b编码成10,c编码成11,等等。这时如果我的文件拿到你的电脑上去,就不能正常显示,也就是我们平常遇到的乱码。

这个问题该怎么解决?一个自然而然的想法是大家共用一套编码系统。前辈们也是这么想的,于是ASCII就出现了。它把每个字符编码成一个长度为7的二进制串,再在前头补上一个0,一共8位,占据一个字节。而且ASCII考虑地很周到,将编码写为十六进制以后,012……刚好对应0x30,0x31,0x32……abc则对应0x61,0x62,0x63……这样使得数字、字母本身的大小与他们对应的编码产生相似性,方便人们记忆。

然而,ASCII也存在问题,就是太小了。早期的计算机只用英文,所以标准ASCII码只对2^7=128个不同的字符进行了编码,而且还富裕了一个bit,统一补为0。而现在计算机已经“飞入寻常百姓家”,光汉字就有成千上万个,更别提什么法语日语西班牙语,小小一个ASCII码怎么够用?于是人们就对ASCII进行了扩展,所以就出现了我们常听到的GB 2312、GBK、GB  18030、Big 5等等。

为什么会有这么多不同的扩展呢?因为不同的人想容纳进去的字符不一样。比如中国人毫无疑问想把汉字都编码进去,但韩国人未必想装那么多汉字进去;同样是中国人,大陆的弄些简体字就够了,港澳台则恐怕要以繁体为主。总而言之,为了满足不同人的需求,出现了不同的字符集,刚刚举的几个例子就是汉字编码先后使用过的几个字符集。

然而,明眼人心里都清楚,这么搞是不方便的,GBK的文件拿去Big5还是会出错。好在这个时候Unicode跳出来了。Unicode,人如其名,想要搞的就是大一统。它把全世界几乎所有语言的字符都拿了进来弄了个字符集,同时还包括encoding methodology、collation等多项内容,构成了一套完整的标准。

不过,Unicode虽然好,却不能直接用。因为从Unicode 2.0(July,1996)开始,Unicode就不再直接将字符编码为二进制串,而是建立了一个码空间(code space),其中包含了17个平面(Unicode plane),每个平面有65536个码位(code point)。略过细节不管,总而言之,这样的结果就是Unicode建立了字符到码位的一一映射,但并没有为字符提供二进制编码。所以,为了建立从字符到二进制编码的映射,现在我们需要把码位和二进制编码对应起来。对应的方式也有很多种,最常见的就是UTF-8。UTF-8是现在互联网上应用最广的一种编码方式。从Unicode码位到UTF-8编码的转换很简单,网上有许多详细的介绍,这里就不做介绍了。

好了,到现在为止,我们已经搞清楚了最基本三件事:1.计算机是以二进制串来储存字符的;2.字符的二进制串编码有多种不同的方式,比如GBK、UTF-8等等。3.读取编码方式不匹配的文件,就会显示乱码,如按照GBK的方式去读取UTF-8的文件。

最后,作为实践,你可以尝试打开记事本,随便输入一些文字,然后保存。看到了吗?在编码那个下拉菜单里,你有多种方式可以选择。输入相同的文字,按不同的编码方式保存,然后用一个十六进制编辑器打开看看,你就会发现编码的异同了。

comments powered by Disqus