分类:
2008-10-05 17:38:14
当今时代是个信息化的时代,信息化是促进社会各个方面发展的重要推动力。我们国家搞信息化,首先要解决的就是中文信息的数字化,将汉字信息转为编码文字。由于历史的原因,存在多种编码标准,人们不可避免的要面对不同编码格式的信息及其转换问题。本文就是要介绍不同的汉字编码标准,及它们之间的区别和联系。由于Unicode是国际通用的编码标准,已经成为主流,因此本文还着重介绍了Unicode中的一些概念。
计算机采用二进制来实现数据的存储和运算。对于数值,可以很自然的转换转成二进制。 对非数值的文字和其他符号进行处理时,就要对其进行数字化处理,用二进制编码来表示文字和符号。字符编码就是以二进制的数字来对应字符集的字符。ANSI的ASCII字符集是世界上最早的一个字符集。它使用7 bits来表示一个字符,总共128个字符。
西文是拼音文字,基本符号比较少,编码比较容易,,在一个计算机系统中,输入、内部处理、存储和输出都可以使用同一代码。汉字由于其复杂性,编码就比较困难。人们在实践中总结出了一个汉字处理的过程模型,如下图所示
汉字 输入 输入 码 国标码 内部码 字型码 汉字输出
在不同的环节使用不同的编码。通常有4类编码,即输入码、国标码、内码、字形码。
① 输入码
输入码所解决的问题是如何使用西文标准键盘把汉字输入到计算机内,属于外码。有各种不同的输入码,主要可以分为三类:数字编码、拼音编码和字编型码。
② 国标码
又称为汉字交换码,在计算机之间交换信息用。用两个字节来表示,每个字节的最高位均为0,因此可以表示的汉字数为214=16384个。例如“中”字的国标码为8680(十进制)或7468(十六进制)。
③ 内码
汉字内码是在设备和信息处理系统内部存储、处理、传输汉字用的代码。无论使用何种输入码,进入计算机后就立即被转换为机内码。规则是将国标码的高位字节、低位字节各自加上128(十进制)或80(十六进制)。例如,“中”字的内码以十六进制表示时应为F4E8。这样做的目的是使汉字内码区别于西文的ASCII,因为每个西文字母的ASCII的高位均为0,而汉字内码的每个字节的高位均为1。
④ 字形码
表示汉字字形的字模数据,因此也称为字模码,是汉字的输出形式。通常用点阵、矢量函数等表示。
早期的计算机使用7位的ASCII编码,为了能够表示其它国家的文字,各国在ASCII的基础上制定了自己的字符集,这些从ANSI标准派生的字符集被习惯的统称为ANSI字符集。为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。随着时代的变迁和新的需求的出现,又发展了GBK和GB18030。
1. GB2312
GB2312或GB2312-80是一个的中国国家标准,全称为《信息交换用汉字编码字符集·基本集》,由中国国家标准总局发布。GB2312一共收录了7445个字符,包括6763个汉字和682个其它符号。下面针对输入码、国标码、内码三个方面来介绍GB2312。
GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为。举例来说,“啊”字是GB2312之中的第一个汉字,它的区位码就是1601。区位码是输入码的一种。
l 01-09区为特殊符号。
l 16-55区为一级汉字,按拼音排序。
l 56-87区为二级汉字,按部首/笔画排序。
l 10-15区及88-94区则未有编码。
汉字的区号、位号各增加32后得到的双7位二进制编码即为汉字的“国标码”。
在使用GB2312的程序中,为了兼容ASCII码,通常采用EUC储存方法,即把两个字节国标码的最高位置“1”,就得到了该汉字的内码。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。GB2312的内码范围见图1中橘红色区域。
假设某个汉字的国标码是G1、G2,其中G1表示第一个字节,G2表示第二个字节。类似地,该汉字的区位码为Q1、Q2,机内码为Jl、J2,则它们之间的换算关系如下:
Q1+32=Gl,Q2十32=G2(区位码一-国标码)
G1+128=J1,G2+128=J2(国标码一-内码)
Q1+160=J1,Q2+160=J2(区位码一-内码)
2. GBK
由于GB2312支持的汉字太少,1995年中华人民共和国全国信息技术标准化技术委员会又制定了《汉字内码扩展规范》GBK1.0。GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。
GBK与GB2312-80信息处理交换码所对应的、事实上的内码标准兼容;同时,在字汇一级支持 ISO/IEC 10646-1 和GB 13000-1 的全部中日韩 (CJK) 汉字(20902字)。GBK除了包含GB2312-80 和GB12345-90中包括的全部非汉字符号外,还涵盖我国台湾地区中文标准交换码TCA-CNS 11643 -92 ( 与其对应的内码为Big5;以下用Big5泛指二者。) 中的绝大多数符号。今天的windows,linux都已经全面支持GBK,GBK在从GB2312向Unicode过渡中起到了承上启下的重要作用。
GBK尽管在字汇一级支持CJK,它在体系结构、代码空间上,仍然完全不同于ISO/IEC 10646 和Unicode。GBK的代码空间如图1所示:
3. GB18030
2000年的GB18030是取代GBK1。0的正式国家标准。全称:国家标准GB18030-2000《信息交换用汉字编码字符集基本集的扩充》 是中国现时最新的内码字集,与GB2312与GBK兼容,包含所有GB13000-93/Unicode 1.1字符。GB18030主要有以下特点:
l 采用多位元编码,每个字可以由1个、2个或4个位元组组成。
l 编码空间庞大,最多可定义160万个字符。
l 支持中国国内少数民族的文字,不需要动用造字区。
表1展示了GB18030的码位范围。
字节数 |
码位空间 |
码位数 | |||
单字节 |
0x00~0x80 |
129 个码位 | |||
双字节 |
第一字节 |
第二字节 |
23940 个码位 | ||
0x81~0xfe |
0x40~0x7e, 0x80~0xfe | ||||
四字节 |
第一字节 |
第二字节 |
第三字节 |
第四字节 |
1587600 个码位 |
0x81~0xfe |
0x30~0x39 |
0x81~0xfe |
0x30~0x39 |
GB18030是信息产品必须遵循的基础性标准,所有正式发布的产品都必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。
从ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。
Unicode是“The universal character encoding”的简称, 它为所有语言、软件、信息技术协议里文本数据的处理、保存和交换提供了基础。历史上有两个组织试图独立设计Unicode。国际标准化组织(ISO)开发了ISO 10646项目,Unicode协会开发了Unicode项目。后来双方认识到世界不需要两个不兼容的统一字符集,双方开始合并工作成果。从Unicode2.0开始,Unicode开始和ISO 10646兼容。Unicode协会现在的最新版本是2005年的Unicode 4.1.0。ISO的最新标准是10646-3:2003。下面介绍一下理解和使用Unicode必须要了解的一些概念。
1. UCS
为了统一表示世界各国的文字,1993年国际标准化组织公布了“Universal Multiple-Octet Coded Character Set”的国际标准ISO/IEC 10646,简称UCS(Universal Code Set),它的目标就是世界上所有的文字规定统一的编码方法。从Unicode2.0开始, Unicode也与UCS兼容。UCS有两种格式:UCS-2和UCS-4。顾名思义,UCS-2就是用两个字节编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)编码。
UCS-4使用4个字节来表示一个字符。其中,第一个字节用来编码组,因为最高位不用,故总共表示128个组。第二个字节编码平面,每组有256个平面。第三个字节编码行,每个平面有256行。第四个字节来编码字位,每行共有256个字位。
组 平面 行 字位 最高位为0 图2
一个字符就被安排在这个编码空间的一个字位上。例如ASCII字符“A”,它的ASCII为41H,而在UCS中的编码则为00000041H,即位于00组、00面、00行的第41H字位上。又如汉字“大”,它在GB2312中的编码为3473H,而在UCS中的编码则为00005927H,即在00组、00面、59H行的第27H字位上。第0组的第0面被称作基本多文种平面(Basic Multilingual Plane), 简称BMP,其它平面称作补充平面(supplementary-plane)。事实上,为了保持和Unicode的兼容,ISO承诺不使用U+0000到U+10FFFF之外的值编码。
将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。UCS-2是对BMP的16位编码方式,它等于TUS1.1的实现。
2. Unicode编码字符集
字符集的编码是指从抽象字符集到唯一数字标识的映射。而这个数字标识只是一个数学符号,与它在计算机中的表示无关。Unicode字符集用整数值编码,每个整数值称为码点(Unicode codepoint)。每个Unicode字符由一个码点唯一确定,Unicode字符也有自己的名字,名字由ASCII码组成,大写。Unicode字符通常由码点+名字指定,如U+0061 LATIN SMALL LETTER A.
Unicode是按文种(Script)编码,而不是按语言、国家或地区编码,比如中日韩汉字属于同一文种,Unicode对它统一编码,这就是CJK,它是“中日韩统一编码汉字”CJK Unified Ideographs的简称。
Unicode最初被设计为使用一个统一的,16位编码方式,但是在与UCS的融合中,人们认识到65536个码点不足以覆盖所有的汉字,于是Unicode采用了UCS的用四个“八位”来表征组、面、行、位的体系结构,但是Unicode只使用第0面到第16面,编码空间从U+0000到U+10FFFF。BMP内主要是常用的字符编码,常用的汉字也都在BMP内。直到Unicode3.1,才开始使用补充平面编码。UCS-2和Unicode1.1都是对BMP编码。第2个面是拼音文字辅助平面,用于古文字及特殊领域内的符号。第3个面是汉字辅助平面。第14个平面是特殊用途平面,第15、16个平面是私有平面,第3到第13个平面目前还没有使用。
以前的关于字符编码的很多工业标准都在这个层次上,他们对抽象字符集合标准化,也可能有名字和属性,但是没有对字符在计算机中编码表示标准化。例如GB2312-80。这些标准需要其他的关于编码格式的标准。
3. Unicode编码格式。
在Unicode字符编码模型中,编码格式(encoding form)指定如何将每个码点表示为一个或多个编码单元序列。Unicode标准提供了三种不同的编码格式,使用8位、16位和32位编码单元,分别为UTF-8、UTF-16、UTF-32。
(1)UTF-16
Unicode的最初目标是使用固定宽度的16位编码格式,于是Unicode1.1采用UCS-2的编码形式,但是只能表示BMP内的字符。为了支持补充平面内的字符,又保持基于16位的编码格式,Unicode设计了UTF-16。
l 对于BMP中的字符,UTF-16值直接等于它的码点(codepoint)
l 对于补充面中的字符,用高位代理(high surrogates)和低位代理(low surrogates)组成的代理对来表示。在BMP中预留的0xD800–0xDFFF就是为了在UTF-16中对补充平面中字符编码。0xD800–0xDBFF 被叫做高位代理,0xDC00–0xDFFF被叫做低位代理,二者组成的代理对正好有1,024 x 1,024 = 1,048,576个组合,恰好等于补充平面中的字符数。
UCS-2在BMP内等同于UTF-16,唯一的区别是UCS-2不支持代理对,没有对补充平面中的字符编码。
(2)UTF-8
由于现实中存在着许多只能处理8位编码的应用,为了在更大范围内推广Unicode,Unicode又设计了基于8位的编码方式UTF-8。UTF-8使用一到四个字节来映射Unicode的编码空间。UTF-8的编码方法如下:
Unicode字符(16进制) UTF-8 字节流(二进制)
U+0000 - U+007F 0xxxxxxx
U+0080 - U+07FF 110xxxxx 10xxxxxx
U+0800 - U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
U+10000 - U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
从TUS2.0开始,Unicode使用UTF-16和UTF-8代替了原来单一的16位编码UCS-2。
(3)UTF-32
从一开始,ISO/IEC 10646就支持32位的编码方式,即UCS-4,所以,Unicode从TUS3.1开始也引入了32位的编码方式UTF-32。
UTF-32的编码最简单,每个字符的编码就是等于该字符码点一个32位整数,编码方法如下:
Unicode字符(16进制) UTF-32 字节流(二进制)
U+0000..U+D7FF, U+E000..U+10FFFF 00000000000xxxxxxxxxxxxxxxxxxxxx
UCS-4是ISO/IEC 10646的32位编码方式,它与UTF-32兼容,除了代码空间的区别。
UCS-4:U+0000..U+7FFFFFFF
UTF-32:U+0000..U+10FFFF
Unicode的3种编码方式没有优劣之分,各有特点,都比以前的多字节编码效率高。3种编码方式同时存在,为开发者提供了巨大的灵活性,使得在保存现有实现下向unicode过渡成为可能,这也是unicode在工业界成功的一大因素。
4. Unicode编码方案
在Unicode标准中,用于Unicode数据字节串行化的各种不同类型的规范被称为Unicode编码方案(encoding scheme)。在字节串行化过程中,必须考虑系统字节顺序问题,是big-endian还是little-endian。
对于UTF-8,在序列中只包括UTF-8的编码单元(1字节),因此,UTF-8中的数据表示不存在字节顺序的问题。但对于16位和32位的编码方案,字节串行化过程必须将编码单元分解为两个或四个字节,并且必须清楚的定义这些字节的顺序。
因此,Unicode标准中定义的三种编码格式,导致总共七种Unicode编码方案,分别为:UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE、UTF-32LE。
显然UTF-16BE、UTF-16LE、UTF-32BE、UTF-32LE显示的标明了字节顺序,但是在现有实现中,确实存在不能提供来标明字节顺序的方式的可能。因此,模糊的编码实现名称UTF-16和UTF-32也是需要的。
在模糊标识下,解释数据前判断字节顺序仍是必须的。码点U+FEFF 就被用来指定字节顺序,称为BOM (Byte Order Mark)。
字符编码格式指在内存或API中的整数数据单元,与字节顺序无关;字符编码方案指字节串行化的数据,如I/O流或者文件,必须制定字节顺序。
5. Code page
目前主流的操作系统的内核都已采用Unicode编码,可以在内核上支持全世界所有的语言文字。但是由于现有的大量程序和文档都采用了某种特定语言的编码,例如GBK,所以操作系统不可能不支持现有的编码,而全部改用Unicode。操作系统使用代码页(code page)来解决这个问题,适应不同的国家和地区。
首先代码页对应一个编码字符集,如GBK对应的代码页是CP936。其次代码页提供字符集到Unicode的映射,通过它,应用程序使用的字符和操作系统可识别的Unicode字符就可以互相转换,操作系统就可以将程序使用的字符编码与键盘上的键或屏幕上显示的字符关联起来。
这里说明一下内码和代码页的关系。内码是指操作系统内部的字符编码。早期操作系统的内码是与语言相关的.现在的Windows在内部统一使用Unicode,然后用代码页适应各种语言,“内码”的概念就比较模糊了。微软一般将缺省代码页指定的编码说成是内码,在特殊的场合也会说自己的内码是Unicode。
注:TUS1.1是Unicode描述版本的方法。
参考文献
1.
2.
3.(编码基本原理)
4.(UTF编码格式)