【问题标题】:Why were the code points in the range of U+D800 to U+DFFF removed from the Unicode character set?为什么从 Unicode 字符集中删除 U+D800 到 U+DFFF 范围内的代码点?
【发布时间】:2017-03-04 06:01:46
【问题描述】:

我正在学习 UTF-16 编码,我读过如果你想表示 U+10000 到 U+10FFFF 范围内的代码点,那么你必须使用代理对,它们在U+D800 转 U+DFFF。

假设我想对以下代码点进行编码:U+10123(二进制为 10000000100100011):

首先我布局这个位序列:

110110xxxxxxxxxx 110111xxxxxxxxxx

然后我用代码点的二进制格式用 x 填充位置:

1101100001000000 1101110100100011(D840 DD23 十六进制)


我也读到 U+D800 到 U+DFFF 范围内的代码点已从 Unicode 字符集中删除,但我不明白为什么要删除此范围!

我的意思是这个范围可以很容易地用 4 个字节编码,例如下面是 U+D812 码位的 UTF-16 编码格式(二进制为 1101100000010010):

1101100000110110 1101110000010010(D836 DC12 十六进制)

注意:我在示例中使用的是 UTF-16 Big Endian。

【问题讨论】:

  • 您确定 U+10123 变为 D840 DD23 而不是 D800 DD23
  • @Roland Illig 很奇怪,当我手动编码时我得到D840 DD23,但是当我使用这个在线工具对其进行编码时:r12a.github.io/apps/conversion,我得到D800 DD23。难道我的手动编码方式不对?
  • 我们称之为保留而不是删除。有助于错误检测,您可以知道谁做错了,并在正确的位置提交错误报告。其他示例是 U+FFFE(向后匹配 BOM)和 U+FFFF(作为 C 文件结尾太容易出错)。
  • @Roland Illig 你是对的,D800 DD23 是正确答案,我做错的是我忘记从代码点中减去0x10000(这应该是我做的第一步)。

标签: unicode encoding character-encoding utf-16


【解决方案1】:

代码点 U+D800 - U+DFFF 专门保留1用于 UTF-16。由于它们不在 U+10000 - U+10FFFF 的范围内,UTF-16 不会使用代理对单独对它们进行编码,因此它会是模棱两可的(非法2) 以使这些单独的代码点以 UTF-16 序列显示为未编码。


根据Unicode.org UTF-16 FAQ

1Q: What are surrogates?

答:代理是来自两个特殊 Unicode 值范围的代码点,保留用作 UTF-16 中成对代码单元的前导值和尾随值。前导,也称为高,代理从 D80016 到 DBFF16,尾随或低,代理从 DC0016 到 DFFF16。它们被称为代理,因为它们不直接表示字符,而只是作为一对

2Q: Are there any 16-bit values that are invalid?

答:未配对的代理在 UTF 中无效。这些包括 D80016 到 DBFF16 范围内的任何值,后跟 DC0016 到 DFFF16,或 DC0016 到 DFFF16 范围内的任何值,前面没有 D80016 到 DBFF16.

【讨论】:

  • 您的措辞是将编码代码点与代码点混合在一起。它们不能在 UTF-16 流中未编码。无法将它们编码为 UTF-16。 UTF-8 和 UTF-32 可以对它们进行编码,但正如您所指出的,它们是保留的,不应编码。
【解决方案2】:

我没有官方来源来支持这一点,但我认为这是为了防止混淆,因此您无法获得可以解释为有效 UTF-16 和有效 UCS-2 的代码序列.与增加 1048576 个新代码点相比,这 2048 个代码点的损失微不足道。

【讨论】:

    【解决方案3】:

    由于将代码点编码为代理对从减去0x010000 开始,这将导致负数。而这个减法的目的是允许多 65536 个代码点,而不是对剩下的 2048 进行编码。如果整个代码空间在遥远的将来用完,也许这将证明是有用的。

    【讨论】:

    • 只有代码点 U+10000 - U+10FFFF 被减去并编码为代理对。代码点 U+0000 - U+FFFF 按原样编码,而不是减去。
    • @Remy 这就是为什么我说“将代码点编码为作为代理对”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 2018-04-01
    • 2010-11-19
    • 2019-05-30
    • 2017-08-03
    • 1970-01-01
    相关资源
    最近更新 更多