资源预览内容
第1页 / 共27页
第2页 / 共27页
第3页 / 共27页
第4页 / 共27页
第5页 / 共27页
第6页 / 共27页
第7页 / 共27页
第8页 / 共27页
第9页 / 共27页
第10页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
- 1 -浅谈文字编码和 Unicodefmddlmyy我曾经写过一篇 谈谈 Unicode 编码,简要解释UCS、UTF、BMP、BOM 等名词(以下简称谈谈 Unicode 编码),在网上流传较广,我也收到不少朋友的反馈。本文探讨谈谈 Unicode 编码中未介绍或介绍较少的代码页、Surrogates 等 问题,补充一些 Unicode 资料,顺带介 绍一下我最近编写的一个 Unicode 工具:UniToy。本文虽然是前文的补充,但在写作上尽量做到独立成篇。标题中的“浅谈” 是对自己的要求,我希望文字能尽量浅显易懂。但本文还是假设读者知道字节、16 进制,了解谈谈 Unicode 编码中介绍过的字节序和 Unicode 的基本概念。0 UniToyUniToy 是我编写的一个小工具。通过 UniToy,我们可以全方位、多角度地查看 Unicode,了解 Unicode 和语言、代码页的关系,完成一些文字编码的相关工作。本文的一些内容是通过 UniToy 演示的。大家可以从我的网站(www.fmddlmyy.cn)下载 UniToy 的演示版本。 1 文字的显 示1.1 发 生了什么?我们首先以 Windows 为例来看看文字显示过程中发生了什么。用记事本打开一个文本文件,可以看到文件包含的文字:如果我们用 UltraEdit 或 Hex Workshop 查看这个文件的 16 进制数据,可以看到:- 2 -我们看到:文件“例子 GBK.txt”有 10 个字节,依次是“D7 D6 B7 FB BA CD B1 E0 C2 EB”,这就是记事本从文件中读到的内容。记事本是用来打开文本文件的,所以它会调用 Windows 的文本显示函数将读到的数据作为文本显示。Windows 首先将文本数据转换到它内部使用的编码格式:Unicode ,然后按照文本的 Unicode 去字体文件中 查找字体图像,最后将图像显示到窗口上。总结一下前面的分析,文字的显示应该是这样的: 步骤 1:文字首先以某种编码保存在文件中。 步骤 2:Windows 将文件中的文字 编码映射到 Unicode。 步骤 3:Windows 按照 Unicode 在字体文件中查找字体图像,画到窗口上。 所谓编码就是用数字表示字符,例如用 D7D6 表示“ 字”。当然,编码还意味着约定,即大家都认可。从谈谈 Unicode 编码中,我们知道Unicode 也是一种文字编码,它的特殊性在于它是由国际组织设计,可以容纳全世界所有语言文字。而我们平常使用的文字编码通常是针对一个区域的语言、文字设计,只支持特定的语言文字。例如:在上面的例子中,文件“ 例子 GBK.txt”采用的就是 GBK 编码。 如果上述 3 个步骤中任何一步 发生了错误,文字就不能被正确显示,例如: 错误 1:如果弄 错了 编码,例如将 Big5 编码的文字当作 GBK 编码,就会出现乱码。 错误 2:如果从特定编码到 Unicode 的映射发生错误,例如文本数据中出现该编码方案未定义的字符,Windows 就会使用缺省字符,通常是? 。- 3 - 如果当前字体不支持要显示的字符,Windows 就会显示字体文件中的缺省图像:空白或方格。 在 Unicode 被广泛使用前,有多少种 语言、文字,就可能有多少种文字编码方案。一种文字也可能有多种编码方案。那么我们怎么确定文本数据采用了什么编码? 1.2 采用了哪种编码?按照惯例,文本文件中的数据都是文本编码,那么它怎么表明自己的编码格式?在记事本的“打开”对话框上:我们可以看到记事本支持 4 种编码格式:ANSI、Unicode、Unicode big endian、UTF-8。如果读者看过谈谈 Unicode 编码,对Unicode、Unicode big endian、UTF-8 应该 不会陌生,其实它们更准确的名称应该是 UTF-16LE(Little Endian)、UTF-16BE(Big Endian)和 UTF-8,它们是基于 Unicode 的不同编码方案。 在谈谈 Unicode 编码 中介绍过,Windows 通过在文本文件开头增加一些特殊字节(BOM)来区分上述 3 种编码,并将没有 BOM 的文本数据按照 ANSI 代码页处 理。那么什么是代 码页 ,什么是 ANSI 代码页? 2 代码页和字符集2.1 Windows 的代码页2.1.1 代码页代码页(Code Page)是个古老的专业术语,据说是 IBM 公司首先使用的。代码页 和字符集的含义基本相同,代码页规定了适用于特定地区的字符集合,和这些字符的编码。可以将代码页理解为字符和字节数据的映射表。Windows 为自己支持的代码页都编了一个号码。例如代码页 936 就是简体中文 GBK,代 码页 950 就是繁体中文 Big5。代码页的概念比较简单,就是一个字符编码方案。但要说清楚 Windows 的 ANSI 代码页,就要从 Windows 的区域(Locale)说起了。 - 4 -2.1.2 区域和 ANSI 代码页微软为了适应世界上不同地区用户的文化背景和生活习惯,在Windows 中设计了区域(Locale)设置的功能。Local 是指特定于某个国家或地区的一组设定,包括代码页,数字、 货币 、时间和日期的格式等。在Windows 内部,其实有两个 Locale 设置:系统 Locale 和用户 Locale。系统 Locale 决定代 码页 ,用户 Locale 决定数字、货币、时间和日期的格式。我们可以在控制面板的“区域和语言选项”中设置系统 Locale 和用户Locale:每个 Locale 都有一个对应的代码页。Locale 和代码页的对应关系,大家可以参阅我的另一篇文章 谈谈 Windows 程序中的字符编码的附录 1。系统 Locale 对应的代码页被作为 Windows 的默认代码页。在没有文本编码信息时,Windows 按照默认代码页的编码方案解释文本数据。这个默认代码页通常被称作 ANSI 代码页(ACP)。ANSI 代码页还 有一层意思,就是微 软自己定 义的代码页。在历史上,IBM 的个人计算机和微软公司的操作系统曾 经是 PC 的标准配置。微软公司将 IBM 公司定义的代码页称作 OEM 代码页,在 IBM 公司的代码页基础上作了些增补后,作为自己的代码页,并冠以 ANSI 的字样。我们在“ 区域和语言选项” 高级页面的代码页转换表中看到的包含 ANSI 字样的代码页都是微软自己定义的代码页。例如: 874 (ANSI/OEM - 泰文) 932 (ANSI/OEM - 日文 Shift-JIS) 936 (ANSI/OEM - 简体中文 GBK) - 5 - 949 (ANSI/OEM - 韩文) 950 (ANSI/OEM - 繁体中文 Big5) 1250 (ANSI - 中欧) 1251 (ANSI - 西里尔文) 1252 (ANSI - 拉丁文 I) 1253 (ANSI - 希腊文) 1254 (ANSI - 土耳其文) 1255 (ANSI - 希伯来文) 1256 (ANSI - 阿拉伯文) 1257 (ANSI - 波罗的海文) 1258 (ANSI/OEM - 越南) 在 UniToy 中,我们可以按照代码页编码顺序查看这些代码页的字符和编码: 我们不能直接设置 ANSI 代码页,只能通 过选择 系统 Locale,间接改变当前的 ANSI 代码页 。微 软定义的 Locale 只使用自己定义的代码页。所以,我们虽 然可以通过“区域和语言选项”中的代码页转换表安装很多代码页,但只能将微软的代码页作为系统默认代码页。2.1.3 代码页转换表在 Windows 2000 以后,Windows 统一采用 UTF-16 作为内部字符编码。 现在,安装一个代码页就是安装一张代码页转换表。通过代码页转换表,Windows 既可以将代码页的编码转换到 UTF-16,也可以将 UTF-16 转换 到代码页的编码 。代码页转换表的具体 实现可以是一个以 nls 为后缀的数据文件,也可以是一个提供转换函数的动态链接库。有的代码页- 6 -是不需要安装的。例如:Windows 将 UTF-7 和 UTF-8 分别作为代码页65000 和代码页 65001。UTF-7、UTF-8 和 UTF-16 都是基于 Unicode 的编码方案。它们之间可以通过简单的算法直接转换,不需要安装代码页转换表。在安装过一个代码页后,Windows 就知道怎样将该代码页的文本转换到 Unicode 文本,也知道怎 样将 Unicode 文本转换成该代码页的文本。例如:UniToy 有导入和导出功能。所谓导入功能就是将任一代码页的文本文件转换到 Unicode 文本;导出功能就是将 Unicode 文本转换到任一指定的代码页。 这里所说的代码页就是指系统已安装的代码页:其实,如果全世界人民在计算机刚发明时就统一采用 Unicode 作为字符编码,那么代码页就没有存在的必要了。可惜在 Unicode 被发明前,世界各国人民都发明并使用了各种字符编码方案。所以,Windows 必须通过代码页支持已经被广泛使用的字符编码。从这种意义看,代码页主要是为了兼容现有的数据、程序和习惯而存在的。2.1.4 SBCS、DBCS 和 MBCSSBCS、DBCS 和 MBCS 分别是单字节字符集、双字节字符集和多字节字符集的缩写。SBCS 、DBCS 和 MBCS 的最大编码长度分别是 1 字节、两字节和大于两字节(例如 4 或 5 字节)。例如:代 码页 1252 (ANSI-拉丁文 I)是单字 节字符集;代 码页 936 (ANSI/OEM-简体中文 GBK)是双字节字符集;代码页 54936 (GB18030 简体中文)是多字节字符集。 单字节字符集中的字符都用一个字节表示。显然,SBCS 最多只能容纳 256 个字符。 - 7 -双字节字符集的字符用一个或两个字节表示。那么我们从文本数据中读到一个字节时,怎么判断它是单字节字符,还是双字节字符的首字符?答案是通过字节所处范围来判断。例如:在 GBK 编码中,单字节字符的范围是 0x00-0x80,双字节字符首字节的范围是 0x81 到 0xFE。我们顺序读取字节数据,如果读到的字节在 0x81 到 0xFE 内,那么这个字节就是双字节字符的首字节。GBK 定义双字节字符的尾字节范围是 0x40 到 0x7E和 0x80 到 0xFE。 GB18030 是多字 节字符集,它的字符可以用一个、两个或四个字 节表示。这时 我们又如何判断一个字节是属于单字节字符,双字节字符,还是四字节字符?GB18030 与 GBK 是兼容的,它利用了 GBK 双字节字符尾字节的未使用码位。GB18030 的四字节字符的第一字 节的范围也是0x81 到 0xFE,第二字节的范围是 0x30-0x39。通过第二字节所处范围就可以区分双字节字符和四字节字符。GB18030 定义四字节字符的第三字节范围是 0x81 到 0xFE,第四字节范围是 0x30-0x39。 2.2 代 码页实 例2.2.1 实例一:GB18030 代码页1.1 节 的“错误 2”中演示了一个全被 显示成?的文件。这个文件的数据是:其实,这是一个包含了 6 个四字节字符的 GB18030 编码的文件。记事本按照 GBK 显示这些数据,而 GB18030 的四字节字符编码在 GBK中是未定义的。Windows 根据首字节范围判断出 12 个双字节字符,然后因为找不到匹配的转换而将其映射到默认字符?。使用 UniToy 按照GB18030 代 码页导入 这个文件,就可以看到: - 8
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号