【问题标题】:What is the maximum number of bytes for a UTF-8 encoded character?UTF-8 编码字符的最大字节数是多少?
【发布时间】:2012-03-20 22:53:44
【问题描述】:

单个 UTF-8 编码字符的最大字节数是多少?

我将加密以 UTF-8 编码的字符串的字节,因此需要能够计算出 UTF-8 编码的字符串的最大字节数。

有人可以确认单个 UTF-8 编码字符的最大字节数

【问题讨论】:

标签: utf-8 character-encoding byte character


【解决方案1】:

根据RFC3629,每个字符的最大字节数为4,这将字符表限制为U+10FFFF

在 UTF-8 中,U+0000..U+10FFFF 范围内的字符(UTF-16 可访问范围)使用 1 到 4 个八位字节的序列进行编码。

(原始规范允许超过U+10FFFF 的代码点最多使用六字节字符代码。)

代码小于 128 的字符只需要 1 个字节,接下来的 1920 个字符代码只需要 2 个字节。除非您使用深奥的语言,否则将字符数乘以 4 将是一个严重的高估。

【讨论】:

  • 对你来说什么是“深奥的语言”?现实世界中存在的任何语言,还是在世界不同语言之间切换的文本? UTF-8-to-String 函数的开发者如果进行过度分配并在实际转换后缩小结果,是否应该选择 2、3 或 4 作为乘数?
  • @rinntech 的“深奥语言”是指一种具有大量高价值 unicode 字符的语言(位于列表底部附近:unicode-table.com/en/sections)。如果您必须过度分配,请选择 4。您可以进行两次传递,一次查看您需要并分配多少字节,然后另一次进行编码;这可能比分配大约 4 倍所需的 RAM 更好。
  • 总是尝试处理最坏的情况:hacker9.com/single-message-can-crash-whatsapp.html
  • CJKV characters 大多占用 3 个字节(一些稀有/古老的字符占用 4 个字节)并称它们为深奥有点牵强(仅中国就占世界人口的近 20%... )。
  • 以前是6个,为什么限制在4个?是什么阻止我们继续使用标准并拥有11111111 的前导字节和2^(6*7) 位空间用于字符?
【解决方案2】:

如果没有进一步的上下文,我会说 UTF-8 中字符的最大字节数是

答案:6 个字节

接受答案的作者正确地指出这是“原始规范”。这通过 RFC-2279 1 有效。正如 J. Cocoe 在下面的 cmets 中指出的那样,这在 2003 年通过 RFC-3629 2 发生了变化,它将 UTF-8 限制为 21 位编码,这可以通过使用四个字节的编码方案来处理。

如果覆盖所有 unicode 则回答:4 个字节

但是,在Java <= v7 中,他们谈到了用 UTF-8 表示 unicode 的最大 3 字节?这是因为原始的 unicode 规范只定义了基本的多语言平面 (BMP),即它是 unicode 的旧版本,或现代 unicode 的子集。所以

如果只表示原始 unicode,则回答 BMP:3 个字节

但是,OP 谈到了另一种方式。不是从字符到 UTF-8 字节,而是从 UTF-8 字节到字节表示的“字符串”。也许接受答案的作者从问题的上下文中得到了这一点,但这并不一定很明显,因此可能会使这个问题的普通读者感到困惑。

从 UTF-8 到原生编码,我们必须看看“字符串”是如何实现的。某些语言,例如 Python >= 3 将用整数代码点表示每个字符,这允许每个字符 4 个字节 = 32 位来覆盖 unicode 所需的 21 个字节,这会造成一些浪费。为什么不完全是 21 位?因为当它们是字节对齐时,事情会更快。一些语言,如 Python Java 使用 UTF-16 编码表示字符,这意味着它们必须使用代理对来表示扩展的 unicode(而不是 BMP)。无论哪种方式,最大仍然是 4 个字节。

如果采用 UTF-8 则回答 -> 本机编码:4 个字节

所以,最后的结论是,4 是最常见的正确答案,所以我们做对了。但是,里程可能会有所不同。

【讨论】:

  • “根据维基百科,这仍然是当前正确的规范”——不再是。在您写完这篇文章后不久(4 月 2 日编辑),Wikipedia 的 UTF-8 文章已更改,以澄清 6 字节版本不是当前 (2003) UTF-8 规范的一部分。
  • “但是,在 Java
  • 没有分配超过 10FFFF(刚刚超过一百万)限制的代码点,并且许多 UTF8 实现从未实现超过 4 个字节的序列(有些只有 3 个字节,例如 MySQL),所以我会考虑它即使考虑与旧实现的兼容性,也可以安全地将每个代码点硬限制为 4 个字节。您只需要确保在进入的过程中丢弃任何无效的内容。请注意,matiu 建议在计算确切字节长度后进行分配是一个很好的建议。
  • "... [U]nicode 最多可以表示 x10FFFF 代码点。所以,包括 0,这意味着我们可以用这些字节来做到这一点:F FF FF,即二加一半字节,或 20 位。”我认为这有点不正确。从 0x0 到 0x10FFFF 的代码点数为 0x110000,可以用 1F FF FF 或 21 位表示。 0x110000 数字对应于每个 0x10000 个代码点的17 planes
  • PSA:维基百科不是真正的来源。查看文章的实际参考文献。
【解决方案3】:

支持 US-ASCII(一种标准英文字母编码)的最大字节数为 1。但随着时间的推移,将文本限制为英文变得越来越不理想或不实用。

Unicode 旨在表示所有人类语言的字形以及多种符号,具有多种呈现特性。 UTF-8 是 Unicode 的一种有效编码,尽管仍然偏向于英语。 UTF-8 是自同步的:通过在任一方向扫描明确定义的位模式,可以轻松识别字符边界。

虽然每个 UTF-8 字符的最大字节数为 3,仅支持平面 0 的 2 字节地址空间,即基本多语言平面 (BMP),在某些应用程序中可以接受为最小支持,但它是4 支持所有 17 个当前 Unicode 平面(截至 2019 年)。需要注意的是,很多流行的“emoji”字符很可能位于Plane 16,需要4个字节。

但是,这仅适用于基本字符字形。还有各种修饰符,例如使重音出现在前一个字符上,也可以将任意数量的代码点链接在一起以构造一个复杂的“字素”。因此,在现实世界的编程中,使用或假设每个字符的最大字节数是固定的,最终可能会给您的应用程序带来问题。

这些考虑意味着 UTF-8 字符串不应该在处理之前“扩展”为固定长度的数组,就像有时所做的那样。相反,应该直接使用专为 UTF-8 设计的字符串函数进行编程。

【讨论】:

  • 注意:关于不使用固定宽度字符数组的段落是我自己的观点。我愿意编辑此答案以响应 cmets。
猜你喜欢
  • 2016-11-26
  • 2013-05-11
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 2015-01-17
  • 1970-01-01
  • 2017-02-04
相关资源
最近更新 更多