1.3.1 ASCII到GBK
ASCII编码
我们知道,二进制可用于表示不同数值,如果事先约定每一种数值对应的文字符号,就可以用来表示文本。
1874年,法国电报服务公司的职员埃米尔·波多(Emile Baudot)创造了一种5位编码方式,又称Baudot编码。Baudot编码整个系统由32个字符组成,编码00被保留下来,字母占26个字符,剩余的5个字符是:回车、空格、换行、数字转义、字符转义,用来调整格式。
然而,5位编码明显不够,数字和符号需要依赖转义,大小写字母也无法区分。这是当时经济上的一种权衡技术。
实际上,英文大小写加上10个数字,已经达到62个字符;如果考虑标点符号,字符数量会超过64个。因此,理想的编码至少应为7位。
1967年,美国信息交换标准码(American Stardard Code for Information Interchange,ASCII)正式发布,采用7位编码,取值范围是0~127,即00h~7Fh。
可以在线查看完整的ASCII编码表。对于像Hello,World!这样的一段文本,它的ASCII码为:
48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21
字符和字节是一一对应的。00通常保留为空字符,代表一个字符串的结束。0x20代表空格。大小写字母之间的差值也为0x20。
128个码位包括大写字母26个、小写字母26个、数字10个、控制符33个、符号33个。
区位码
ASCII码只有128个码位,而常用的汉字有6000多个,这显然是不够的。
为了解决这个问题,在20世纪80年代,国际标准化组织(ISO)及国际电工委员会(IEC)联合制定了ISO/IEC 8859,简称ISO 8859。DOS时代的汉字系统和汉字输入法就建立在ISO 8859之上。
同时,为了解决汉字的计算机编码问题,我国也制定了对应的国家标准,即国标第2312号,简称GB 2312。由于该标准于1980年发布,也叫作GB 2312—1980,这个标准能编码6763个简体汉字。
GB 2312的基础,是汉字的区位码,分为94个区,每个区都保留96个码位,头尾2个码位被保留为空,剩余94个码位用于表示汉字字符。这样共有94×94=8836个可用码位,但GB 2312实际使用了其中的7445个,还有一些空区/空码。
例如,“啊”字的区位码是1601,表示第16区的第1个字符。“诚”字的区位码是1947,表示第19区的第47个字符。
区位码使用十进制表示,而GB 2312则使用十六进制表示,范围是0xA1A1~10xFEFE。这里从0xA1到0xFE正好是94个区/码,如图1-10所示。选择从0xA1(161)开始是为了与ASCII码(0~127)兼容,同时保持一定的后续扩展能力。
图1-10 GB 2312中的汉字
图1-11中的算法实现了区位码和GB 2312的相互转换。
图1-11 区位码和GB 2312的相互转换
要将区位码转换成GB 2312,只需要将高、低字节分别加上0xA0,反之减去0xA0即可。
GB 2312
GB 2312编码了7445个字符、94个区,汉字在16~55区和56~87区,如图1-12所示。
图1-12 GB 2312符号表
汉字共有6763个,其中包含一级字库3755个和二级字库3008个。非汉字符号有682个,包括符号202个、序号60个、数字22个、拉丁符号52个、日文符号169个、希腊符号48个、俄文符号66个、拼音符号26个、注音符号37个。
这个标准于1981年5月实施,是DOS时代使用的汉字编码标准。
GBK编码
随着计算机的普及,人们对各种字符的需求不断增加。因此,1995年12月,GB的扩展标准GBK得以推出。
GBK可以表示21 886个字符,分为5部分。GBK1、GBK2与GB 2312兼容,并新增717个字符。GBK3新增6080个汉字,GBK4新增8160个汉字,GBK5新增166个符号,如图1-13所示。
图1-13 GBK符号表
GBK编码表示一个字符,可以分为1、2、4字节。
·如果首字节在0x00~0x7F,则这段编码与ASCII编码一致。
·如果首字节为0x80或0xFF,则为无效编码。
·如果首字节在0x81~0xFE,且第二字节在0x40~0xFE,则为两字节编码。
·如果首字节在0x81~0xFE,且第二字节在0x30~0x39,则为四字节编码,其第三、四字节重复第一、二字节的模式,其余为无效字节。
根据以上规则,可以编写一个函数,用于获取一个GBK字节流中的字符数[14]。
GBK标准是为了使计算机能够兼容汉字而开发的。随着计算机在世界范围内的普及,国际上越来越希望有一种统一的文字编码,能够兼容全球所有的文字,这就是Unicode编码。下一节我们将详细介绍Unicode编码。