Open SyMind opened 3 years ago
原文:http://www.unicode.org/reports/tr17/
本文档阐明了一些用于描述字符编码的术语,以及 Unicode 的不同形式适用于哪些地方。它将互联网体系架构委员会(Internet Architecture Board,IAB)的三层文本流细化为四层结构。
此文档已被 Unicode 成员和其他相关方审阅过,并已被 Unicode 联盟批准出版。这是一份稳定的文档,可以用作参考资料或被其他规范引用为规范性参考资料。
Unicode 字符编码模型的四个层级可以概括为:
除了这四个独立的层级之外,还有两个实用的概念:
IAB 模型,被定义在 [RFC 2130] 中,分为三个层级:编码字符集(Coded Character Set, CCS),字符编码方案(Character Encoding Scheme,CES)和传输编码语法(Transfer Encoding Syntax,TES)。但是,为了充分应对 Unicode 字符编码模型的需要,定义了四个层级。其中,抽象字符表被隐式地定义在 IAB 模型中。Unicode 模型将 TES 独立于模型之外,同时在 CCS 和 CES 之间添加了一个额外的层级。
下面的部分给出了四个层级的定义、解释和示例,以及字符映射和传输编码语法。
抽象字符表被定义为要编码的无序的抽象的字符的集合。抽象 的意思是这些对象是按照约定定义的。
字符表由两种类型: 封闭的(fixed) 或 开放的(opened) 。在大多数字符编码中,封闭的字符表通常很小。字符表一旦确立,就永不变更。向指定的字符表添加一个新的抽象字符将创建一个新的字符表,然后给字符一个编号,构成一个新的对象。对于 Unicode 标准来说,字符表天生就是开放的。因为 Unicode 是通用编码,任何可被编码的抽象字符都是字符表的潜在成员,无论该字符当前是否已知。
字符表的例子:
Unicode 标准通过发布主要版本和次要版本对字符表进行版本控制:1.0、1.1、2.0、2.1、3.0 等。每个版本的字符表由包含在该版本中的抽象字符枚举所定义。
Unicode 标准的字符表现在是严格按增量扩充的,尽管由于[Unicode]和[10646]的合并,在最早的版本(1.0 和 1.1)中没有完全保证增量扩充,影响了向后兼容性。从 2.0 版开始,Unicode 字符编码稳定性策略[Stability]保证了不会从字符表中移除任何字符。
注意:Unicode 字符编码稳定性策略也以其他形式限制对标准的变更。例如,许多字符属性受到一致性的约束,一些属性一旦被分配就不能变更。对规范化稳定性的保证防止了变更会破坏现有编码字符的映射,也限制了未来的版本中可以被添加到字符表中的字符类型。
字符表的元素是抽象字符。字符不同于字形,字形是代表一个字符或字符一部分的特殊图像。相同字符的字形可能有非常不同的形状,如下图所示的字母 a。
字形并不总是对应一个字符。例如,序列“f”后跟“ i”可以显示为单个字形,称为“连字”。请注意,字形已合并在一起,点从“ i”中消失,如下图所示。
另一方面,可以通过两个字形序列来实现 fi,如下图中所示的假想示例。是使用单个字形还是使用两个字形的序列取决于字体和渲染软件。
与大多数字符表不同,Unicode 覆盖范围是所有字符。考虑到编写系统时的复杂性,在实际中这意味着几乎所有的实现都只是支持字符表的某个子集,而非所有字符。
Unicode 标准没有预设子集,每个实现都需要定义并支持它希望解析的字符表的子集。
编码字符集被定义为一个从抽象字符集到非负整数集的映射。整数范围不必是连续的。在 Unicode 标准中,Unicode 标量值显式定义了这样一个不连续的整数范围。
如果编码字符集将一个抽象字符映射一个整数,则视为它被定义在了一个编码字符集中。该整数是指定抽象字符的 码点(code point ) 。然后,这个抽象字符就是一个编码字符。
编码字符集是 ISO 和字符编码委员会产出的基本对象。它们将已定义的字符表与非负整数关联起来,然后可以明确地使用非负整数来引用字符表中的特定抽象字符。
编码字符集也可以称为字符编码(character encoding)、编码字符表(coded character repertoire)、字符集定义(character set definition)或代码页(code page)。
负责字符编码的 JTC1 小组委员会 SC2 要求为其编码字符集中的每个抽象字符分配唯一的字符名。供应商编码的字符集或 SC2 以外的标准委员会产出的编码通常不遵循这种做法,在这些编码中,为字符提供的名称通常都是变量和注释,而不是字符编码的标准部分。
被用于映射抽象字符的非负整数范围定义代码空间的相关概念。代码空间类型的传统边界与编码方式密切相关(见下文),因为抽象字符到非负整数的映射是在特定的编码方式下完成的。有效代码空间的例子有 0..7F、0..FF、0..FFFF、0..10FFFF、0..7FFFFFFF、0..FFFFFFFF。
字符编码方式是从 CCS 中的整数集到 码元(code unit ) 序列集的映射。码元是一个整数,表示在计算机体系结构中占用特定二进制的宽度,例如 8 位字节。编码方式将字符表示为计算机中的实际数据。码元序列不一定具有相同的长度。
编码字符集的字符编码方式被定义为映射该编码字符集中所有编码字符的字符编码方式。
注意:在许多情况下,对于给定的编码字符集只有一种字符编码方式。在某些情况下,只指定了字符编码方式。依赖码元序列和整数之间的隐式关系,隐式定义了编码字符集。
解析一个字符序列时,由三种可能性:
CCS 的编码方式可以产生与抽象字符相关的固定宽度或可变宽度的码元序列。编码方式可能涉及 CCS 的整数到一组码元序列的任意可逆映射。
编码方式有多种类型。下面是一些有关编码方式的更重要的例子。
定宽编码方式的例子:
变宽编码方式的例子:
编码方式定义了编码的一个基本问题:每个字符有多少码元。每个字符的码元数量对国际化软件很重要。在以前,这等同于每个字符需要多少字节表达。随着 Unicode 和 10646 引入 UCS-2、UTF-16、UCS-4 和 UTF-32,它泛化为两个概念:码元的规范宽度,和用于表示每个字符所需的码元数量。与 ISO/IEC 10646 相关联的 UCS-2 编码方式,仅能表示 BMP 中的字符,是一种定宽编码方式。相比之下,UTF-16 使用一个或两个码元,能够覆盖整个 Unicode 的代码空间。
UTF-8 是一个很好的例子。在 UTF-8 中,用于表示字符数据的基本码元是 8 位宽(即一个字节或八位)。UTF-8 的宽度映射为:
用于特定编码字符集的编码方式示例:
字符编码方案(CES)是从码元序列到字节序列的可逆转换,用以下三种方法中的一种:
字符编码方案与跨平台持久化数据的问题相关,例如码元比字节宽,在这种情况下,可能需要进行字节交换以将数据匹配指定平台的字节顺序。特别是
重要的是不要混淆字符编码方式(CEF)和 CES。
一些 Unicode 编码方案与三种 Unicode 编码方式的命名相同。在不加限定地使用时,术语 UTF-8、UTF-16 和 UTF-32 是作为Unicode 编码方式还是作为 Unicode 编码方案并不明确。这种不明确对 UTF-8 通常是无危险的,因为 UTF-8 编码方案很容易从 UTF-8 编码方式定义的字节序列派生出来。然而,对于 UTF-16 和 UTF-32,这种不明确就有问题了。作为编码方式,UTF-16 和 UTF-32 的码元通过 16 位或 32 位的数据类型访问内存;它没有相关的字节顺序,也没有使用 BOM。
作为编码方案,UTF-16 和 UTF-32 表示序列化字节,例如数据流或文件中的序列化字节;它们的字节顺序是两种中的一种,并且数据的首部可能有一个 BOM。当 UTF-16 或 UTF-32 的使用可能会被误解,并且它们作为 Unicode 编码方式或 Unicode 编码方案的使用之间的区别很重要时,应该使用完整的术语。例如,使用 UTF-16 编码方式或 UTF-16 编码方案。它们也可以分别缩写为 UTF-16 CEF 或 UTF-16 CES。
Unicode 字符编码方案的例子:
Unicode 标准有 7 种字符编码方案:UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE 和 UTF-32LE。
压缩字符编码方案的例子:
处理器架构对多字节机器整数映射到存储位置的处理方式不同。小端架构将最低有效字节放在较低的地址,而大端架构从最高有效字节开始。
操作内存中的码元时,这种差异无关紧要,但是当使用指定的 CES 将码元序列化为字节序列时,字节顺序就变得重要了。在读取数据流时,有两种字节顺序:与处理器读取的字节顺序相同或相反。在前一种情况下,不需要采取特别的操作;在后一种情况下,数据在处理之前需要进行字节反转。
根据数据流的外部标记,区分三种字节顺序:Big Endian(BE)、Little Endian(LE)和 默认或内部标记(default or internally marked) 。
在 Unicode 中,码点为 U+FEFF 的字符被定义为字节顺序标记,而它的字节反转后对应的码点 U+FFFE 是 UTF-16 中的非字符(U+FFFE)。因此,在数据流首部,字节顺序标记用于明确地表示码元的字节顺序。
概要
本文档阐明了一些用于描述字符编码的术语,以及 Unicode 的不同形式适用于哪些地方。它将互联网体系架构委员会(Internet Architecture Board,IAB)的三层文本流细化为四层结构。
状态
此文档已被 Unicode 成员和其他相关方审阅过,并已被 Unicode 联盟批准出版。这是一份稳定的文档,可以用作参考资料或被其他规范引用为规范性参考资料。
内容
1 字符编码模型
Unicode 字符编码模型的四个层级可以概括为:
除了这四个独立的层级之外,还有两个实用的概念:
IAB 模型,被定义在 [RFC 2130] 中,分为三个层级:编码字符集(Coded Character Set, CCS),字符编码方案(Character Encoding Scheme,CES)和传输编码语法(Transfer Encoding Syntax,TES)。但是,为了充分应对 Unicode 字符编码模型的需要,定义了四个层级。其中,抽象字符表被隐式地定义在 IAB 模型中。Unicode 模型将 TES 独立于模型之外,同时在 CCS 和 CES 之间添加了一个额外的层级。
下面的部分给出了四个层级的定义、解释和示例,以及字符映射和传输编码语法。
2 抽象字符表
抽象字符表被定义为要编码的无序的抽象的字符的集合。抽象 的意思是这些对象是按照约定定义的。
字符表由两种类型: 封闭的(fixed) 或 开放的(opened) 。在大多数字符编码中,封闭的字符表通常很小。字符表一旦确立,就永不变更。向指定的字符表添加一个新的抽象字符将创建一个新的字符表,然后给字符一个编号,构成一个新的对象。对于 Unicode 标准来说,字符表天生就是开放的。因为 Unicode 是通用编码,任何可被编码的抽象字符都是字符表的潜在成员,无论该字符当前是否已知。
字符表的例子:
2.1 版本控制
Unicode 标准通过发布主要版本和次要版本对字符表进行版本控制:1.0、1.1、2.0、2.1、3.0 等。每个版本的字符表由包含在该版本中的抽象字符枚举所定义。
Unicode 标准的字符表现在是严格按增量扩充的,尽管由于[Unicode]和[10646]的合并,在最早的版本(1.0 和 1.1)中没有完全保证增量扩充,影响了向后兼容性。从 2.0 版开始,Unicode 字符编码稳定性策略[Stability]保证了不会从字符表中移除任何字符。
2.2 字符与字形
字符表的元素是抽象字符。字符不同于字形,字形是代表一个字符或字符一部分的特殊图像。相同字符的字形可能有非常不同的形状,如下图所示的字母 a。
字形并不总是对应一个字符。例如,序列“f”后跟“ i”可以显示为单个字形,称为“连字”。请注意,字形已合并在一起,点从“ i”中消失,如下图所示。
另一方面,可以通过两个字形序列来实现 fi,如下图中所示的假想示例。是使用单个字形还是使用两个字形的序列取决于字体和渲染软件。
2.4 子集
与大多数字符表不同,Unicode 覆盖范围是所有字符。考虑到编写系统时的复杂性,在实际中这意味着几乎所有的实现都只是支持字符表的某个子集,而非所有字符。
Unicode 标准没有预设子集,每个实现都需要定义并支持它希望解析的字符表的子集。
3 编号字符集
编码字符集被定义为一个从抽象字符集到非负整数集的映射。整数范围不必是连续的。在 Unicode 标准中,Unicode 标量值显式定义了这样一个不连续的整数范围。
如果编码字符集将一个抽象字符映射一个整数,则视为它被定义在了一个编码字符集中。该整数是指定抽象字符的 码点(code point ) 。然后,这个抽象字符就是一个编码字符。
编码字符集是 ISO 和字符编码委员会产出的基本对象。它们将已定义的字符表与非负整数关联起来,然后可以明确地使用非负整数来引用字符表中的特定抽象字符。
编码字符集也可以称为字符编码(character encoding)、编码字符表(coded character repertoire)、字符集定义(character set definition)或代码页(code page)。
3.1 字符命名
负责字符编码的 JTC1 小组委员会 SC2 要求为其编码字符集中的每个抽象字符分配唯一的字符名。供应商编码的字符集或 SC2 以外的标准委员会产出的编码通常不遵循这种做法,在这些编码中,为字符提供的名称通常都是变量和注释,而不是字符编码的标准部分。
3.2 代码空间
被用于映射抽象字符的非负整数范围定义代码空间的相关概念。代码空间类型的传统边界与编码方式密切相关(见下文),因为抽象字符到非负整数的映射是在特定的编码方式下完成的。有效代码空间的例子有 0..7F、0..FF、0..FFFF、0..10FFFF、0..7FFFFFFF、0..FFFFFFFF。
4 字符编码方式
字符编码方式是从 CCS 中的整数集到 码元(code unit ) 序列集的映射。码元是一个整数,表示在计算机体系结构中占用特定二进制的宽度,例如 8 位字节。编码方式将字符表示为计算机中的实际数据。码元序列不一定具有相同的长度。
编码字符集的字符编码方式被定义为映射该编码字符集中所有编码字符的字符编码方式。
解析一个字符序列时,由三种可能性:
CCS 的编码方式可以产生与抽象字符相关的固定宽度或可变宽度的码元序列。编码方式可能涉及 CCS 的整数到一组码元序列的任意可逆映射。
编码方式有多种类型。下面是一些有关编码方式的更重要的例子。
定宽编码方式的例子:
变宽编码方式的例子:
编码方式定义了编码的一个基本问题:每个字符有多少码元。每个字符的码元数量对国际化软件很重要。在以前,这等同于每个字符需要多少字节表达。随着 Unicode 和 10646 引入 UCS-2、UTF-16、UCS-4 和 UTF-32,它泛化为两个概念:码元的规范宽度,和用于表示每个字符所需的码元数量。与 ISO/IEC 10646 相关联的 UCS-2 编码方式,仅能表示 BMP 中的字符,是一种定宽编码方式。相比之下,UTF-16 使用一个或两个码元,能够覆盖整个 Unicode 的代码空间。
UTF-8 是一个很好的例子。在 UTF-8 中,用于表示字符数据的基本码元是 8 位宽(即一个字节或八位)。UTF-8 的宽度映射为:
用于特定编码字符集的编码方式示例:
用于特定编码字符集的编码方式示例:
5 字符编码方案
字符编码方案(CES)是从码元序列到字节序列的可逆转换,用以下三种方法中的一种:
字符编码方案与跨平台持久化数据的问题相关,例如码元比字节宽,在这种情况下,可能需要进行字节交换以将数据匹配指定平台的字节顺序。特别是
重要的是不要混淆字符编码方式(CEF)和 CES。
一些 Unicode 编码方案与三种 Unicode 编码方式的命名相同。在不加限定地使用时,术语 UTF-8、UTF-16 和 UTF-32 是作为Unicode 编码方式还是作为 Unicode 编码方案并不明确。这种不明确对 UTF-8 通常是无危险的,因为 UTF-8 编码方案很容易从 UTF-8 编码方式定义的字节序列派生出来。然而,对于 UTF-16 和 UTF-32,这种不明确就有问题了。作为编码方式,UTF-16 和 UTF-32 的码元通过 16 位或 32 位的数据类型访问内存;它没有相关的字节顺序,也没有使用 BOM。
作为编码方案,UTF-16 和 UTF-32 表示序列化字节,例如数据流或文件中的序列化字节;它们的字节顺序是两种中的一种,并且数据的首部可能有一个 BOM。当 UTF-16 或 UTF-32 的使用可能会被误解,并且它们作为 Unicode 编码方式或 Unicode 编码方案的使用之间的区别很重要时,应该使用完整的术语。例如,使用 UTF-16 编码方式或 UTF-16 编码方案。它们也可以分别缩写为 UTF-16 CEF 或 UTF-16 CES。
Unicode 字符编码方案的例子:
Unicode 标准有 7 种字符编码方案:UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE 和 UTF-32LE。
压缩字符编码方案的例子:
字节顺序
处理器架构对多字节机器整数映射到存储位置的处理方式不同。小端架构将最低有效字节放在较低的地址,而大端架构从最高有效字节开始。
操作内存中的码元时,这种差异无关紧要,但是当使用指定的 CES 将码元序列化为字节序列时,字节顺序就变得重要了。在读取数据流时,有两种字节顺序:与处理器读取的字节顺序相同或相反。在前一种情况下,不需要采取特别的操作;在后一种情况下,数据在处理之前需要进行字节反转。
根据数据流的外部标记,区分三种字节顺序:Big Endian(BE)、Little Endian(LE)和 默认或内部标记(default or internally marked) 。
在 Unicode 中,码点为 U+FEFF 的字符被定义为字节顺序标记,而它的字节反转后对应的码点 U+FFFE 是 UTF-16 中的非字符(U+FFFE)。因此,在数据流首部,字节顺序标记用于明确地表示码元的字节顺序。