C++ 编程/软件国际化/文本编码
文本,特别是用来生成可读文本的字符,依赖于字符编码方案。该方案将给定字符集(有时称为代码页)中的字符序列与其他东西配对,例如自然数序列、八位字节序列或电脉冲序列,以便于使用其数字表示。
一个容易理解的例子是摩尔斯电码,它将拉丁字母的字母编码为一系列长短的电报键按下;这类似于 ASCII 如何将字母、数字和其他符号编码为整数。
字节最重要的用途可能是保存字符代码。键盘输入、屏幕显示和打印机打印的字符都有数值。为了使其能够与世界其他地区通信,IBM PC 使用 ASCII 字符集的一种变体。ASCII 字符集 中有 128 个定义的代码。IBM 使用剩余的 128 个可能值来扩展字符代码,包括欧洲字符、图形符号、希腊字母和数学符号。
在早期计算中,ASCII(1963 年)和 EBCDIC(1964 年)等编码字符集的引入开始了标准化的过程。此类集合的局限性很快显现出来,并开发了许多临时方法来扩展它们。需要支持多种书写系统(语言),包括东亚脚本的 CJK 家族,需要支持更多的字符,并需要对字符编码采用系统方法,而不是以前临时的方法。
Unicode 是一种行业标准,其目标是提供一种方法,使所有形式和语言的文本都可以编码以供计算机使用。Unicode 6.1 于 2012 年 1 月发布,是当前版本。它目前包含来自 93 种文字系统的 109,000 多个字符。由于 Unicode 只是将数字分配给字符的标准,因此还需要有将这些数字编码为字节的方法。三种最常见的字符编码是 UTF-8、UTF-16 和 UTF-32,其中 UTF-8 是迄今为止最常用的编码。
在 Unicode 标准中,平面 是数值(码点)的组,指向特定字符。Unicode 码点在逻辑上划分为 17 个平面,每个平面有 65,536 (= 216) 个码点。平面由 0 到 16十进制 的数字标识,对应于六位格式(hhhhhh)中前两位的可能值 00-10十六进制。截至版本 6.1,这六个平面中的六个已分配了码点(字符),并已命名。
平面 0 - 基本多语言平面 (BMP)
平面 1 - 补充多语言平面 (SMP)
平面 2 - 补充表意文字平面 (SIP)
平面 3–13 - 未分配
平面 14 - 补充专用平面 (SSP)
平面 15–16 - 补充专用区 (S PUA A/B)
BMP | SMP | ||
---|---|---|---|
0000–0FFF | 8000–8FFF | 10000–10FFF | 18000-18FFF |
1000–1FFF | 9000–9FFF | 11000–11FFF | 19000-19FFF |
2000–2FFF | A000–AFFF | 12000–12FFF | 1A000-1AFFF |
3000–3FFF | B000–BFFF | 13000–13FFF | 1B000-1BFFF |
4000–4FFF | C000–CFFF | 14000-14FFF | 1C000-1CFFF |
5000–5FFF | D000–DFFF | 15000-15FFF | 1D000–1DFFF |
6000–6FFF | E000–EFFF | 16000–16FFF | 1E000–1EFFF |
7000–7FFF | F000–FFFF | 17000-17FFF | 1F000–1FFFF |
SIP | SSP | |
---|---|---|
20000–20FFF | 28000–28FFF | E0000–E0FFF |
21000–21FFF | 29000–29FFF | |
22000–22FFF | 2A000–2AFFF | |
23000–23FFF | 2B000–2BFFF | |
24000–24FFF | ||
25000–25FFF | ||
26000–26FFF | ||
27000–27FFF | 2F000–2FFFF |
目前,大约 10% 的潜在空间被使用。此外, Unicode 联盟已为所有已知的现代和古代书写系统(文字系统)临时映射出了字符范围。虽然 Unicode 最终可能需要使用另一个备用平面来表示表意文字,但其他平面仍然存在。即使发现了之前未知的文字系统,其中包含数万个字符,但 1,114,112 个码点的限制也不太可能在短期内达到。Unicode 联盟已声明该限制永远不会改变。
奇怪的限制(不是 2 的幂)不是由于 UTF-8 造成的,UTF-8 的设计限制为 231 个码点(32768 个平面),并且即使限制为 4 个字节,也可以编码 221 个码点(32 个平面),而是由于 UTF-16 的设计造成的。在 UTF-16 中,两个 16 位 字 的“代理对”用于编码 220 个码点 1 到 16,此外还使用单个字来编码平面 0。
UTF-8 是 Unicode 的可变长度编码,每个字符使用 1 到 4 个字节。它旨在与 ASCII 兼容,因此,单字节值在 UTF-8 中表示的字符与它们在 ASCII 中表示的相同。因为 UTF-8 流不包含 '\0',所以您可以直接在现有的 C++ 代码中使用它,无需进行任何移植(除了在计算其中的“实际”字符数时除外)。
UTF-16 也是可变长度的,但它使用 16 位单元而不是 8 位单元,因此每个字符由 2 个或 4 个字节表示。这意味着它与 ASCII 不兼容。
与前两种编码不同,UTF-32 不是 可变长度的:每个字符都由正好 32 位表示。这使得编码和解码变得更容易,因为 4 字节值直接映射到 Unicode 代码空间。缺点是空间效率低下,因为每个字符都需要 4 个字节,无论它是什么。