计算机字符编码

上传人:飞*** 文档编号:33885453 上传时间:2018-02-18 格式:DOC 页数:11 大小:547KB
返回 下载 相关 举报
计算机字符编码_第1页
第1页 / 共11页
计算机字符编码_第2页
第2页 / 共11页
计算机字符编码_第3页
第3页 / 共11页
计算机字符编码_第4页
第4页 / 共11页
计算机字符编码_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《计算机字符编码》由会员分享,可在线阅读,更多相关《计算机字符编码(11页珍藏版)》请在金锄头文库上搜索。

1、 字符编码的问题看似很小,经常被技术人员忽视,但是很容易导致一些莫名其妙的问题。这里总结了一下字符编码的一些普及性的知识,希望对大家有所帮助。 还 是得从 ASCII码说 起 说到字符编码,不得不说ASCII码的简史。计算机一开始发 明的时候是用来解决数字计算的问题,后来人们发现,计算机还可以做更多的事,例如文本处理。但由于计算机只识“数”,因此人们必须告诉计算机哪个数字来代表哪个特定字符,例如65代表字母A,66代表字母B ,以此类推。但是计算机之间字符-数字的对应关系必须得一致,否则就会造成同一段数字在不同计算机上显示出来的字符不一样。因此美国国家标准协会ANSI制定了一个标准,规定了常用

2、字符的集合以及每个字符对应的编号,这就是ASCII字符集(Character Set),也称ASCII码。 当时的计算机普遍使用8比特字节作为最小的存储和处理单元,加之当时用到的字符也很少,26个大小写英文字母还有数字再加上其他常用符号,也不到 100个,因此使用7个比特位就可以高效的存储和处理ASCII码,剩下最高位1比特被用作一些通讯系统的奇偶校验。 注意,字节代表系统能够处理的最小单位,不一定是8比特。只是现代计算机的事实标准就是用8比特来代表一个字节。在很多技术规格文献中,为了避免产生歧义,更倾向于使用8位组(Octet)而不是字节(Byte)这个术语 来强调8个比特的二进制流。下文中

3、为了便于理解,我会延用大家熟悉的“字节”这个概念。 ASCII 字符集由95 个可打印字符( 0x20-0x7E)和33 个控制字符(0x00-0x19, 0x7F) 组成。可打印字符用于显示在输出设备上,例如荧屏或者打印纸上,控制字符用于向计算机发出一些特殊指令,例如0x07会让计算机发出哔的一声,0x00 通常用于指示字符串的结束,0x0D 和 0x0A 用于指示打印机的打印 针头退到行首(回车)并移到下一行(换行)。 那时候的字符编解码系统非常简单,就是简单的查表过程。例如将字符序列编码为二进制流写入存储设备,只需要在ASCII字符集中依次找到字符 对应的字节 ,然后直接将该字节写入存储

4、设备即可。解码二进制流的过程也是类似。 OEM 字符集的衍生 当计算机开始发展起来的时候,人们逐渐发现,ASCII字符集里那可怜的 128个字符已经不能再满足他们的需求了。人们就在想,一个字节能够表示的数字(编号)有256个,而ASCII 字符只用到了0x000x7F,也就是占用了前128个,后面128 个数字不用白不用,因此很多人打起了后面这 128 个数字的主意。可是问题在于,很多人同时有这样的想法,但是大家对于0x80-0xFF这后面的128个数字分别对应 什么样的字符,却有各自的想法。 这就导致了当时销往世界各地的机器上出现了大量各式各样的OEM字符集。 下面这张表是IBM-PC 机推

5、出的其中一个 OEM字符集,字符集的前128个字符和 ASCII字符集的基本一致(为 什么说基本一致呢,是因为前 32 个控制字符在某些情况下会被IBM-PC机当作可打印字符解释),后面128个字符空间加入了一些欧洲国家用到的重音字符,以及一些用于画线条画的字符。 事实上,大部分OEM字符集是兼容 ASCII字符集的,也就是说,大家对于0x000x7F这个范围的解释基本是相同的,而对于后半部分 0x800xFF 的解释却不一定相同。甚至有时候同样的字符在不同OEM字符集中对应的字节也是不同的。 不同的OEM字符集导致人们无法跨机器交流各种文档。例如职员甲发了一封简历 rsums给职员乙,结果职

6、员乙看到的却是r sum s,因为字符在职员甲机器上的OEM字符集中对应的字节是0x82,而在职员 乙的机器上,由于使用的OEM字符集不同,对0x82字节解码后得到的字符却是 。 多字 节 字符集( MBCS)和中文字符集 上面我们提到的字符集都是基于单字节编码,也就是说,一个字节翻译成一个字符。这对于拉丁语系国家来说可能没有什么问题,因为他们通过扩展第8个比特,就可以得到256个字符了,足够用了。但是对于亚洲国家来说,256个字符是远远不够用的。因此 这些国家的人为了用上电脑,又要保持和ASCII字符集的兼容,就 发明了多字节编码方式,相 应的字符集就称为多字节字符集。例如中国使用的就是双字

7、节字符集编码(DBCS,Double Byte Character Set)。 对于单字节字符集来说,代码页中只需要有一张码表即可,上面记录着256个数字代表的字符。程序只需要做简单的查表操作就可以完成编解码的过程。 代码页是字符集编码的具体实现,你可以把他理解为一张“字符-字节”映射表,通过查表实现“字符-字节” 的翻译。下面会有更详细的描述。 而对于多字节字符集,代码页中通常会有很多码表。那么程序怎么知道该使用哪张码表去解码二进制流呢?答案是,根据第一个字节来选择不同的码表进行解析。 例如目前最常用的中文字符集GB2312,涵盖了所有简体字符以及一部分其他字符;GBK(K 代表扩展的意思)

8、则在GB2312的基础上加入了对繁体字符等其他非简体字符(GB18030字符集不是双字节字符集,我们在讲Unicode的时候会提到)。这两个字符集的字符都是使用1-2个字节 来表示。 Windows系统采用936代码页来实现对GBK字符集的编解码。在解析字节流的时候,如果遇到字节的最高位是0的话,那么就使用936代码页中的第 1张码表 进行解 码,这就和单字节字符集的编解码方式一致了。 当字节的高位是1的时候,确切的说,当第一个字节位于0x81 0xFE 之间时,根据第一个字节不同找到代码页中的相应的码表,例如当第一个字节是0x81,那么对应936中的下面这张码表: (关于936代码页中完整的

9、码 表信息,参见MSDN :http:/ 按照936代码页的码表,当程序遇到 连续字节流0x81 0x40的时候,就会解码为“丂”字符。 ANSI标 准、国家 标 准、 ISO标 准 不同ASCII衍生字符集的出现 ,让文档交流变得非常困难,因此各种 组织都陆续进行了标准化流程。例如美国ANSI组织制定了ANSI标准字符编码(注意,我们现在通常说到ANSI编码,通常指的是平台的默认编码,例如英文操作系统中是ISO-8859-1,中文系统是GBK),ISO组织制定的各种ISO标准字符编码,还有各国也会制定一些国家标准字符集,例如中国的GBK,GB2312和GB18030 。 操作系统在发布的时候

10、,通常会往机器里预装这些标准的字符集还有平台专用的字符集,这样只要你的文档是使用标准字符集编写的,通用性就比较高了。例如你用GB2312字符集编写的文档,在中国大陆内的任何机器上都能正确显示。同时,我们也可以在一台机器上阅读多个国家不同语言的文档了,前提是本机必须安装该文档使用的字符集。 Unicode的出 现 虽然通过使用不同字符集,我们可以在一台机器上查阅不同语言的文档,但是我们仍然无法解决一个问题:在一份文档中显示所有字符。为了解决这个问题,我们需要一个全人类达成共识的巨大的字符集,这就是Unicode字符集。 Unicode字符集概述 Unicode字符集涵盖了目前人类使用的所有字符,

11、并为每个字符进行统一编号,分配唯一的字符码(Code Point)。Unicode字符集将所有字符按照使用上的频繁度划分为17个层面(Plane),每个层面上有2 16=65536 个字符码空 间。 其中第0个层面 BMP,基本涵盖了当今世界用到的所有字符。其他的 层面要么是用来表示一些远古时期的文字,要么是留作扩展。我们平常用到的 Unicode 字符,一般都是位于BMP层面上的。目前Unicode字符集中尚有大量字符空 间未使用。 编码系统的变化 在Unicode出现之前,所有的字符集都是和具体编码方案绑定在一起的,都是直接将字符和最终字节流绑定死了,例如ASCII编码 系统规定使用7 比

12、特来编码ASCII字符集;GB2312以及GBK 字符集,限定了使用最多2 个字节来编码所有字符,并且规定了字节序。这样的编码系统通常用简单的查表,也就是通过代码页就可以直接将字符映射为存储设备上的字节流了。例如下面这个例子: 这种方式的缺点在于,字符和字节流之间耦合得太紧密了,从而限定了字符集的扩展能力。假设以后火星人入住地球了,要往现有字符集中加入火星文就变得很难甚至不可能了,而且很容易破坏现有的编码规则。 因此Unicode在设计上考虑到了这一点,将字符集和字符编码方案分离开。 也就是说,虽然每个字符在Unicode字符集中都能找到唯一确定的编号(字符码,又称Unicode码),但是决定

13、最终字节流的却是具体的字符编码。例如同样是对 Unicode字符“A”进行编码,UTF-8 字符编码得到的字节流是0x41,而UTF-16(大端模式)得到的是0x00 0x41。 常见的Unicode编码 UCS-2/UTF-16 如果要我们来实现Unicode字符集中BMP字符的编码方案,我 们会怎么实现?由于BMP 层面上有216=65536 个字符码,因此我们只需要两个字节就可以完全表示这所有的字符了。 举个例子,“中” 的Unicode字符码是0x4E2D(01001110 00101101),那么我们可以编码为01001110 00101101(大端)或者00101101 01001

14、110 (小端)。 UCS- 2和UTF-16对于BMP层面的字符均是使用2个字节来表示,并且编码得到的结果完全一致。不同之处在于,UCS-2最初 设计的时候只考虑到BMP字符,因此使用固定2个字节长度,也就是说,他无法表示Unicode其他层面上的字符,而 UTF-16为了解除这个限制,支持Unicode全字符集的编解码,采用了变长编码,最少使用2个字节,如果要编码BMP 以外的字符, 则需要4 个字节结对,这里就不 讨论那么远,有兴趣可以参考维基百科:UTF-16/UCS-2。 Windows 从NT时代开始就采用了UTF-16编码,很多流行的编程平台,例如.Net,Java,Qt还有 M

15、ac下的Cocoa等都是使用 UTF-16作为基础的字符编码。例如代码中的字符串,在内存中相应的字节流就是用UTF-16编码过的。 UTF-8 UTF-8应该是目前应用最广泛的一种Unicode编码方案。由于UCS- 2/UTF-16对于ASCII 字符使用两个字节进行编码,存储和处理效率相对低下,并且由于ASCII 字符经过UTF-16编码后得到的两个字节,高字节始终是0x00,很多C语言的函数都将此字节视为字符串末尾从而导致无法正确解析文本。因此一开始推出的时候遭到很多西方国家的抵触,大大影响了Unicode的推行。后来聪明的人们发明了UTF-8编码,解决了这个问题。 UTF-8编码方案采

16、用1-4 个字节来编码字符,方法其实也非常简单。 (上图中的x代表Unicode码的低8位,y代表高8 位) 对于ASCII字符的编码使用单字节,和ASCII 编码一摸一样,这样所有原先使用ASCII编解码的文档就可以直接转到UTF-8编码 了。对于其他字符,则使用 2-4个字 节来表示,其中,首字节 前置1 的数目代表正确解析所需要的字 节数,剩余字节的高2位始终是10。例如首字节是1110yyyy,前置有3个1 ,说明正确解析总共需要3个字节,需要和后面 2个以 10开头的字节结合才能正确解析得到字符。 关于UTF-8的更多信息,参考维基百科:UTF-8。 GB18030 任何能够将Unicode字符映射为字节流的编码都属于Unicode编码。中国的GB18030编码,覆盖了Unicode所有的字符,因此也算是一种Unicode编码。只不

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号