转载于:http://it.hexun.com/2009-06-01/118203513.html
5.2 知识点介绍
5.2.1 关于字符及编码
首先,我们要知道一些概念和标准。
字符和字节是两个容易混淆的概念,下面我们来看一下它们的含义。
字符:人们用来表示某种意义的符号,如"1"、"a"、"字"等。
字节:字节是存储空间的基本计量单位,由8个二进制位构成。
字符串:零个或多个字符组成的有限序列。
字符集:字符的集合,由于历史原因形成了多种标准,主要包括以下几种:
ASCII字符集
ANSI字符集
Unicode字符集
这些字符集包含什么又有什么关系呢?
这个问题的答案就是计算机字符集的发展历史。
ASCII(美国信息交换标准委员会American Standards Committee forInformationInterchange)字符集,是计算机产生之初为英文通信设计的7位字符集。包含了基本的英文字母、数字、标点符号等128个字符。
随着计算机的广泛应用,为了可以在计算机中保存更多的信息,增加了新的字母、符号,还加入了很多画表格时需要用到的横线、竖线、交叉等形状。这些新增的字符从用128到255之间的数字进行表示,它们构成的字符集通常被称为"扩展字符集"。
计算机进入中国后为了表示汉字(仅常用汉字就有6000多个),我们规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(称为高字节)从0xA1用到0xF7,后面一个字节(称为低字节)从0xA1到0xFE,这样就可以组合出7445个简体汉字。在这些编码里,还把数学符号、罗马希腊的字母、日文的假名都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编成了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。这种汉字方案叫做"GB2312",是对ASCII的中文扩展。
由于汉字太多,我们不得不再一次增加字符的使用范围,只要第一个字节大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。扩展之后的编码方案被称为GBK标准,GBK包括了GB2312的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。后来我们再扩展,又加了几千个新的少数民族的字,GBK扩成了GB18030。
程序员们将其通称为"DBCS"(双字节字符集Double ByteCharecterSet),最大的特点是两字节长的汉字字符和一字节长的英文字符并存,因此中文处理时必须要注意字串里每一个字节的值,如果这个值是大于127的,就可以将下两个字节作为一个双字节编码,而不用管低字节的高位是什么。
与此同时各个国家和地区所制定的不同ANSI编码标准中,都只规定了各自语言所需的"字符"。这些ANSI编码标准所规定的内容包含两层含义:
标准中包含哪些文字和符号,而这些"字符"的集合称为"字符集"。
规定每个"字符"分别用几个字节存储。用什么值来表示这些字符,这个规定就叫做"编码"。
因为当时各个国家都搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码,连中国大陆和中国台湾使用着同一种语言的地区,也分别采用了不同的DBCS编码方案--GB2313(中国大陆)和BIG5(中国台湾)编码,装错了字符系统,显示就会乱了套。
这时,ISO的国际组织决定着手解决这个问题。他们重新搞了一个包括地球上所有文字和符号的编码--"UniversalMultiple-OctetCoded Character Set",简称UCS,就是我们现在常说的"Unicode"。
Unicode在制定时没有考虑与任何一种现有的编码方案保持兼容,这使得GBK与Unicode在汉字的内码编排上是完全不一样的,没有一种简单的算法可以使文本内容在Unicode编码和ANSI编码间进行转换,这种转换必须通过查表来进行。
Unicode开始制定时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是ISO就直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于ASCII里的那些字符,Unicode保持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他语言的文字和符号则全部重新统一编码。由于英文符号只需要用到低8位,所以其高8位永远是0,因此这种方案在保存英文文本时会浪费一倍的空间。
从Unicode开始,无论是半角的英文字母,还是全角的汉字,都是统一的"一个字符"。同时,也都是统一的"两个字节"(这里要注意"字符"和"字节"两个概念的不同,"字节"是物理存储的基本计量单位,而"字符"则是一个文化相关的符号)。在Unicode中,一个字符就是两个字节。
多种字符集存在时,那些生产多语言软件的公司为了在不同的国家销售同一套软件,就不得不在区域化软件时注意双字节字符集,不仅要处处小心不要搞错,还要把软件中的文字在不同的字符集中转来转去。Unicode对于他们来说是一个很好的一揽子解决方案,于是从WindowsNT开始,微软把它们的操作系统改了一遍,把所有的核心代码都改成了用Unicode方式工作的版本,从这时开始,Windows系统终于无须加装各种本土语言系统,就可以显示全世界上所有文化的字符了。
如前所述,Unicode是用两个字节来表示一个字符,总共可以组合出65535个不同的字符,这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系,ISO已经准备了UCS-4方案,就是四个字节来表示一个字符,这样就可以组合出21亿个不同的字符(最高位规定为0)。
为了解决Unicode的传输问题,产生了面向传输的UTF(通用字集转换格式--Universal CharacterSetTransformationFormat)标准,顾名思义,UTF-8就是以8位为单元对UCS进行编码,UTF-16以16位为单元对UCS进行编码,Unicode与UTF之间可以通过一些算法和规则来相互转换。
从计算机对多国语言的支持角度看,大致可以分为三个阶段,如表5-1所示。
表5-1 编码规则对比表
系统内码
说 明
系 统
阶段一:
ASCII编码
计算机刚开始只支持英语,其他语言不能够在计算机上存储和显示
英文DOS
阶段二:
ANSI编码
(本地化)
为使计算机支持更多语言,通常使用0x80~0xFF范围的2个字节来表示1个字符。
不同的国家和地区制定了不同的标准,由此产生了GB2312、BIG5、JIS等不同的编码标准。这些使用2个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI编码。在简体中文系统下,ANSI编码代表GB2312编码,在日文操作系统下,ANSI编码代表JIS编码。
不同ANSI编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字存储在同一段ANSI编码的文本中
中文DOS
中文Windows 95/98
日文Windows 95/98
续表
系统内码
说 明
系 统
阶段三:Unicode
(国际化)
为了使国际间信息交流更加方便,国际组织制定了Unicode字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求
Windows NT/2000/XP
Linux
由于不同ANSI编码所规定的标准是不相同的,因此,对于一个给定的多字节字符串,我们必须知道它采用的是哪一种编码规则,才能够知道它包含了哪些"字符"。而对于Unicode字符串来说,不管在什么环境下,它所代表的"字符"内容总是不变的