您的位置:首页 > 其它

XML学习笔记(一):关于字符编码的理解

2004-08-20 16:22 411 查看
历史上, 有两个独立的,创立单一字符集的尝试。一个是国际标准化组织(ISO)的 ISO 10646 项目,另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 Unicode 项目。幸运的是, 1991年前后,两个项目的参与者都认识到,世界不需要两个不同的单一字符集。它们合并双方的工作成果, 并为创立一个单一编码表而协同工作。两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容,并紧密地共同调整任何未来的扩展。Unicode最初设计是作为一种固定宽度的16位字符编码。但是现在看来,16位编码的所有65536个字符并不能完全表示全世界所有正在使用或曾经使用的字符。于是,Unicode标准已经扩展到包含1112064个字符。那些超出原来的16位限制的字符被称作增补字符。Unicode标准2.0版是第一个包含启用增补字符设计的版本。但是,直到 3.1 版才收入第一批增补字符集。中国政府要求支持 GB18030(一种对整个 Unicode 字符集进行编码的字符编码标准),因此,如果是 Unicode 3.1 版或更新版本,则将包括增补字符。不幸的是,引入增补字符使字符模型变得更加复杂了。在过去,我们可以简单地说“字符”,在一个基于 Unicode 的环境(例如 Java 平台)中,假定字符有 16 位,而现在我们需要更多的术语。

字符是抽象的最小文本单位。它没有固定的形状(可能是一个字形),而且没有值。。“A”是一个字符,“€”(德国、法国和许多其他欧洲国家通用货币的标志)也是一个字符。

字符集是字符的集合。例如,汉字字符是中国人最先发明的字符。

编码字符集是一个字符集,它为每一个字符分配一个唯一数字。Unicode 标准的核心是一个编码字符集,字母“A”的编码为 0041和字符“€”的编码为 20AC。Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,所以“A”的编码书写为“U+0041”。

代码点是指可用于编码字符集的数字。编码字符集定义一个有效的代码点范围,但是并不一定将字符分配给所有这些代码点。有效的 Unicode 代码点范围是 U+0000 至 U+10FFFF。Unicode 4.0 将字符分配给一百多万个代码点中的 96,382 代码点。

增补字符是代码点在 U+10000 至 U+10FFFF 范围之间的字符,也就是那些使用原始的 Unicode 的 16 位设计无法表示的字符。从 U+0000 至 U+FFFF 之间的字符集有时候被称为基本多语言面 (BMP)。因此,每一个 Unicode 字符要么属于 BMP,要么属于增补字符。

字符编码方案是从一个或多个编码字符集到一个或多个固定宽度代码单元序列的映射。最常用的代码单元是字节,但是 16 位或 32 位整数也可用于内部处理。UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案。

通用字符集 (Universal Character Set, UCS)由国际标准 ISO 10646 定义。 UCS 是所有其他字符集标准的一个超集。与其他字符集是双向兼容的。就是说, 如果你将任何文本字符串翻译到 UCS格式,然后再翻译回原编码,你不会丢失任何信息。

UCS 包含了用于表达所有已知语言的字符。ISO 10646 定义了一个 31 位的字符集。 然而,在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD)。这个 UCS 的 16位子集称为 基本多语言面 (Basic Multilingual Plane, BMP)。将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字),且只有专家在历史和科学领域里才会用到它们。按当前的计划, 将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了。ISO 10646-1 标准第一次发表于 1993 年,定义了字符集与 BMP 中内容的架构。定义 BMP 以外的字符编码的第二部分 ISO 10646-2 正在准备中,但也许要过好几年才能完成。新的字符仍源源不断地加入到 BMP 中,但已经存在的字符是稳定的且不会再改变了。

UCS 不仅给每个字符分配一个代码,而且赋予了一个正式的名字。表示一个 UCS 或 Unicode 值的十六进制数,通常在前面加上 "U+",就象 U+0041 代表字符"拉丁大写字母A"。UCS 字符 U+0000 到 U+007F 与 US-ASCII(ISO 646) 是一致的, U+0000 到 U+00FF 与 ISO 8859-1(Latin-1) 也是一致的。从 U+E000 到U+F8FF,已经 BMP 以外的大范围的编码是为私用保留的。

UCS里有些编码点分配给了组合字符。它们类似于打字机上的无间隔重音键。 单个的组合字符不是一个完整的字符。它是一个类似于重音符或其他指示标记,加在前一个字符后面。因而, 重音符可以加在任何字符后面。那些最重要的被加重的字符 在 UCS 里都有自己的位置,以确保同老的字符集的向后兼容性。既有自己的编码位置,又可以表示为一个普通字符跟随一个组合字符的被加重字符,被称为预作字符(precomposed characters)。UCS 里的预作字符是为了同没有预作字符的旧编码,比如 ISO 8859,保持向后兼容性而设的。组合字符机制允许在任何字符后加上重音符或其他指示标记,这在科学符号中特别有用,比如数学方程式和国际音标字母,可能会需要在一个基本字符后组合上一个或多个指示标记。组合字符跟随着被修饰的字符。比如, 德语中的元音变音字符 ("拉丁大写字母A 加上分音符"),既可以表示为 UCS 码 U+00C4 的预作字符,也可以表示成一个普通 "拉丁大写字母A" 跟着一个"组合分音符":U+0041 U+0308 这样的组合。当需要堆叠多个重音符,或在一个基本字符的上面和下面都要加上组合标记时,可以使用多个组合字符。比如在泰国文中,一个基本字符最多可加上两个组合字符。

UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。很明显,它是内部处理最方便的表达方式,但是,如果作为一般字符串表达方式,则要消耗更多的内存。

UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码。值 U+0000 至 U+FFFF 编码为一个相同值的 16 位单元。增补字符编码为两个代码单元,第一个单元来自于高代理范围(U+D800 至 U+DBFF),第二个单元来自于低代理范围(U+DC00 至 U+DFFF)。这在概念上可能看起来类似于多字节编码,但是其中有一个重要区别:值 U+D800 至 U+DFFF 保留用于 UTF-16;没有这些值分配字符作为代码点。这意味着,对于一个字符串中的每个单独的代码单元,软件可以识别是否该代码单元表示某个单单元字符,或者是否该代码单元是某个双单元字符的第一个或第二单元。这相当于某些传统的多字节字符编码来说是一个显著的改进,在传统的多字节字符编码中,字节值 0x41 既可能表示字母“A”,也可能是一个双字节字符的第二个字节。

UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码。U+0000 至 U+007F 使用一个字节编码,U+0080 至 U+07FF 使用两个字节,U+0800 至 U+FFFF 使用三个字节,而 U+10000 至 U+10FFFF 使用四个字节。UTF-8 设计原理为:字节值 0x00 至 0x7F 始终表示代码点 U+0000 至 U+007F(Basic Latin 字符子集,它对应 ASCII 字符集)。这些字节值永远不会表示其他代码点,这一特性使 UTF-8 可以很方便地在软件中将特殊的含义赋予某些 ASCII 字符。

Unicode 提供了一种标准的方法来编码多语言,而我们常用的GB编码仅包含了汉字和ascii字符。基本上,假如从显示的角度理解,假如用户软件仅支持GB,假如输入汉字“啊”,就是将“啊”从内码(0xB0A1)转换为Unicode(0x554A),通过0x554A查询码表得到点阵字库中的“啊”字存储位置,获得点阵数组,显示。

4E00--9FFF:CJK Unified Ideographs 这是汉字在码表中的位置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: