【问题标题】:Are 6 octet UTF-8 sequences valid?6 个八位字节的 UTF-8 序列是否有效?
【发布时间】:2011-04-03 07:35:29
【问题描述】:

UTF-8 能否编码 5 或 6 字节序列,允许编码所有 Unicode 字符?我得到了相互矛盾的标准。我需要能够支持每个 Unicode 字符,而不仅仅是 U+0000..U+10FFFF 范围内的那些。

(所有引用均来自RFC 3629

第 3 节:

在 UTF-8 中,U+0000..U+10FFFF 范围内的字符(UTF-16 可访问范围)使用 1 到 4 个八位字节的序列进行编码。这 只有一个“序列”的八位字节将高位设置为 0, 其余 7 位用于对字符编号进行编码。在一个 n 个八位字节的序列,n>1,初始八位位组有 n 个高阶 位设置为 1,然后是位设置为 0。其余位 该八位字节包含要成为的字符数中的位 编码。以下八位字节都将高阶位设置为 1 和后面的位设置为 0,每个保留 6 位包含 要编码的字符中的位。

所以不是所有可能的字符都可以用 UTF-8 编码?这是否意味着我不能对来自不同于 BMP 的平面的字符进行编码?

第 2 节:

八位字节值 C0、C1、F5 到 FF 永远不会出现。

这意味着我们不能用 5 或 6 个八位字节(甚至一些不在上述范围内的 4 个八位字节)编码 UTF-8 值?

第 12 节:

将字符范围限制为 0000-10FFFF(UTF-16 可访问范围)。

查看之前的 RFC 证实了这一点……他们缩小了字符范围。

第 10 节:

编码为 UTF-8 时会出现另一个安全问题:ISO/IEC UTF-8 的 10646 描述允许编码字符数最多 U+7FFFFFFF,产生最多 6 个字节的序列。因此有 如果字符数的范围不是缓冲区溢出的风险 明确限制为 U+10FFFF 或者如果缓冲区大小不考虑 考虑 5 字节和 6 字节序列的可能性。

所以这些序列是根据 ISO/IEC 10646 定义允许的,但不是 RFC 3629 定义?我应该关注哪一个?

提前致谢。

【问题讨论】:

    标签: unicode utf-8


    【解决方案1】:

    它们不是超过 10FFFF 的 Unicode 字符,BMP 覆盖 0000 到 FFFF。

    UTF-8 定义良好,适用于 0-10FFFF。

    【讨论】:

    • 谢谢,这是有道理的。这是否意味着我只需要担心长度超过 4 个八位字节的 UTF-8 序列,任何更长的时间都会出错?
    • @PatrickNiedzielski 是的,但您必须将它们视为错误 (MUST)。
    • @devio, Unicode 的未来版本在扩展时会怎样?
    • 平面 3–13 仍未分配。我想我们不应该担心;)en.wikipedia.org/wiki/Plane_(Unicode)
    【解决方案2】:

    UTF-8 和 UTF-16 都允许对所有 Unicode 字符进行编码。 UTF-8 不允许做的是编码上、下代理一半(UTF-16 使用)或高于 U+10FFFF 的值,这不是合法的 Unicode。

    注意 BMP 以 U+FFFF 结束。

    【讨论】:

      【解决方案3】:

      我不得不说不:Unicode 代码点在 [0, 0x10FFFF] 范围内有效,并且映射到 1-4 个八位字节。因此,如果您确实遇到了一个 5 或 6 字节的 UTF-8 编码代码点,那么它不是一个有效的代码点——那里肯定没有分配任何内容。我有点困惑,为什么它们会出现在 ISO 标准中——我找不到解释。

      这确实让你想知道,如果也许在未来的某一天,它们会扩展到超过 U+10FFFF。 0x10FFFF 允许超过一百万个字符,但是那里有很多字符,这取决于最终编码了多少。 (为了理智,我们希望不要,一百万个字符很多!)UTF-32 可以处理更多的代码点,正如您所发现的,UTF-8 可以。不幸的是,UTF-16 真的很不幸——在代码点范围内的某个地方需要更多的代理对。

      【讨论】:

      • ISO 原本打算引入自己的 31 位字符编码。 UTF-8 就是围绕这种可能性而设计的。
      • 对我来说,似乎 Unicode 正试图填补其余的代码点......他们拥有的东西比他们知道的要多。例子:有一个麻将的积木。但是,在 BMP 之外肯定有一些我需要支持的有用字符。不过大部分都是垃圾。这让我想知道为什么他们不久前不接受克林贡字符。
      • @dan04:确实如此。这就是为什么你可以拥有比 0x10_FFFF 高得多的代码点的抽象字符,因为你没有将它们用于 UTF 交换。 (有时这些被称为 superssupras。)例如,perl -le 'print ord chr(0xFFF_FFFF_FFFF)' 打印 17592186044415。这可以很方便。
      猜你喜欢
      • 1970-01-01
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2016-04-25
      • 1970-01-01
      • 2015-07-04
      • 2012-03-25
      相关资源
      最近更新 更多