闲谈字符和字符集以及编码(上)

这几天在工作中接连有同事遇到和字符集、字符编码相关的问题,一个问题是在黑莓平台上葡萄牙语的资源文件在保存时正确选择编码的问题,一个是要支持汉字转拼音的问题;在解决问题之余,导致我有了写一篇比较详细的文章的打算。提纲写完后才发现不是那么好开展,比较棘手的一个问题是还没有找到一个令我满意的有关字符这一术语的通俗易懂而又精准的定义。我的初中老师对我说,概念不清,寸步难行,于是这个比较正式一些的文档只好稍后再进行。然而这不影响我写现在的这篇闲谈,在本文中我避开了这些术语的精准定义,而采用大家皆可心领神会的方法直接使用之。

在我看来,“字符”有本质和表示两层上的含义。其本质上,应该是人类文化中所在某个特定范围内共同认可具有一定含义或者作用的文字字元或者符号(文字其实也是符号,为了符合惯用法,分别列出)。在表示上,尤其是在计算机领域之内,应该是对具有其本质作用的个体进行编号。根据编号,再使用其他方式来规范统一其呈现(主要是视觉方面,当然也涉及听觉等其他方面,例如盲文还可能关系到触觉)。有 C 语言基础的朋友们对此应该毫不意外,char 其实就是 int,这在一定程度上透露出了,计算机认为字符就是个数字。正因为是这样,几乎所有的字符集在确定了所收录的字符的同时,也就确定了其中的单个元素所对应的数值,这个字符与数值的对应关系,称之为编码。一般来讲,一个字符集都只使用一种编码方案,因此,日常的文档中也会用编码方案的名称来指称对应的字符集。例如,GB2312 是一个以简体汉字为主的字符集的编码方案,同时也经常用来作为该字符集本身的名字。
从发展过程来看,每一个字符集都是着重于处理当时现实中的迫切需求,即使有一定的前瞻性考虑,也并不很强,当然,这种情形也和当时的计算机应用状况密切关联,尤其是地域性,所以很多字符集都仅限于解决当地语言文字的输入输出和显示问题。从感性多一点的理解上,可以把字符集当成是一本字典所收录的字的总目录。由此,字符集有几个和字典类似的特性,1、字符集之间可能是包容关系,例如 GB2312 和 GBK 的关系,就像你的中学生英汉辞典与朗文辞典的关系;2、字符集之间也可能毫无关系,比如 GB2312 和某个只包括阿拉伯语字符的字符集,就像是新华字典和朗文辞典的关系;3、不存在收录了世间所有字符的完全字符集,只有当前收录字符最全的字符集。

与汉字相关的字符集,我们经常听到的有 GB2312、BIG5、GBK、UNICODE 等。GB2312 的制定时间很早,是在 1980 年,由于“历史局限性”,此字符集内收录的字符很少,汉字总共收录了 6763 个,而且全部都是大陆通用的简体汉字。GB,是“国标”二字的汉语拼音首字母,也因此 GB2312 的发音应该是国标 2312。在此标准肆虐横行的同时,我们的港澳台同胞,也制定了一个适用于当地繁体汉字需要的字符集,其对应编码名为 BIG5,也有人称之为大五码。

此处会引入一个比较有趣的问题,大多数搞不清楚字符集之间的区别与联系的人都是因为在这里没弄明白。按道理讲,各个字符集你用你的编码,我用我的编码,井水不犯河水,在哪个字符集的编码范围之内,就显示该字符集内对应的字符,不就完了吗?怎么常常会出现非要用户指定一个字符集才能正确显示内容,使用别的字符集查看就是乱码呢?这是因为,字符集之间的字符尽管可以认为没有交集(不要从字符本身所具有的人类可理解的含义方面考虑。比如一个汉字“阿”,即使没有在简体和繁体间存在字形上的差别,我们也可以认为它在简体中文的字符集和繁体中文的字符集中是不同的字),但其所使用的编码互相是有重叠的。举例来说,简体汉字字符集 GB2312 中的第一个汉字“啊”,其编码为 B0A1,而在 BIG5 中,相同编码的汉字为“陛”。这还是你的运气好,在另外的字符集中,很显然就不一定会是一个你可以识别的字符了。

1993 年,Unicode 1.1 标准发布,其中收录了中国大陆、台湾、日本、韩国所使用的字符(这些字符的集合又被称为 CJK) 20902 个,紧接着,中国将该标准正式采用为国家标准,是为 GB13000.1。同年,随着计算机文字处理需求的发展,又对 GB2312 进行了扩展,收录了更多的字符。这个扩展后的规范(请注意,当时还不是标准)被称为 GBK,K 就是“扩”的拼音首字母。具体的需求示例之一,就是如果不扩展的话,当时的总理朱镕基的姓名中的“镕”字将无法处理。在 GBK 中,收录的汉字字符个数大幅增加,BIG5 中的所有字符更是无一遗漏(当然,字符对应的编码变了)。GB2312 中已经收录的字符其编码则保持不变,因此,GBK 不止在收录的字符数量上是 GB2312 的超集,在字符编码的技术实现方案上也兼容了原来的 GB2312。GBK 被微软公司实现到了 Windows 95 和 Windows NT 3.51 中,对应的代码页为 936。由于微软操作系统的广泛使用,导致 GBK 在当时成为了事实标准。到 1995 年,中国国家信息技术标准化技术委员会才将 GBK 敲定,并确定了版本号 1.0。GBK 1.0 对微软实现的 936 代码页做了轻微的修订,向其中新增了 95 个字符,这些字符在 GB13000.1 中是没有的,于是被临时指定到了 Unicode 中的私用区(PUA)中。特别指出,CJK 中的所有字符,GBK 中都是有的。后来,微软又向 936 代码页中增加了欧元符号,但指定的编码(0x80)在 GBK 中是一个不合法的值(准确术语为代码点,即 code point)。

到了 2000 年,GB18030 国标发布。在保持兼容的前提下对 GBK 进行了扩充。GB18030 的字符数目大大增加,以至于两个字节已经无法满足编码要求,于是将编码一个字符所需的可能字节数上限提到了 4。而其中的由一个字节或者两个字节可以表示的这部分字符,有时也被称做 GBK。当然,这个 GBK 中的字符在 Unicode 中的对应关系与前文提到的 GBK 1.0 略有差异,因为那 95 个字符已经随着 Unicode 本身的发展,部分被收录到了 Unicode 中,而不必再停留在 PUA 中。

不知不觉写了不少了,本来还要写 UCS 和 UTF 相关的内容的,留待下次吧。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注