ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

确实查看了常见资源,例如 Wikipedia's UTF-8 Article,首先...对吗?
我阅读了几篇给出不同答案的文章......我实际上得到的印象是答案是 3 所以我很高兴我问了
我将在此处留下一个 youtube 链接,其中包含 Tom Scott 的字符、符号、Unicode 奇迹:goo.gl/sUr1Hf。您将听到并了解一切是如何从 ASCII 字符编码演变为 utf-8 的。

C
Community

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

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

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

代码小于 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) 位空间?
C
Community

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

答案:6 个字节

接受答案的作者正确地将其指出为“原始规范”。这在 RFC-2279 1 中是有效的。正如 J. Cocoe 在下面的评论中指出的那样,这在 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 位来覆盖我们需要的 21 个 unicode,但有一些浪费。为什么不完全是 21 位?因为当它们是字节对齐时,事情会更快。一些语言,如 Python <= 2 和 Java 使用 UTF-16 编码表示字符,这意味着它们必须使用代理对来表示扩展的 unicode(而不是 BMP)。无论哪种方式,这仍然是最大 4 个字节。

回答是否使用 UTF-8 -> 本机编码:4 个字节

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


“根据维基百科,这仍然是当前和正确的规范”——不再是。在您写完这篇文章后不久(4 月 2 日编辑),Wikipedia 的 UTF-8 文章已更改,以澄清 6 字节版本不是当前 (2003) UTF-8 规范的一部分。
“但是,在 Java <= v7 中,他们谈论用 UTF-8 表示 unicode 的最大 3 字节?那是因为原始的 unicode 规范只定义了基本的多语言平面”——这可能是最初的原因,但是这不是全部。 Java 使用“修改后的 UTF-8”,其中一个修改是它“使用自己的两倍三字节格式”而不是“标准 UTF-8 的四字节格式”(他们的话)。
没有分配超过 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:维基百科不是真正的来源。查看文章的实际参考。
D
David Spector

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

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

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

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

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


注意:关于不使用固定宽度字符数组的段落是我自己的观点。我愿意编辑此答案以回应评论。
另请注意,克林贡语也是 unicode,因此它不仅仅是人类语言。至于您的建议,这将归结为您正在优化什么以及基准告诉您什么。有时,在没有条件逻辑或分支的情况下翻阅已知数量的字节会更快。分支会严重损害性能。如果您对其进行了预处理,您仍然必须进行分支,但至少较重的计算内容会在没有零分支的情况下通过连续内存进行撕裂。如果你想优化空间,虽然这不是一个好主意。
克林贡语是一种人类语言,这意味着它是由马克·奥克朗 (Marc Okrand) 和其他人类为实现人类目的而设计的。克林贡语不是外星语言,因为不存在克林贡语星球。至于您对使用六字节数组进行内部字符处理的常见做法的明显辩护,我们将不得不同意不同意。这样的限制是错误。
使用 UTF 编码,最大字节数为 4。根据使用的符号,您可以使用 1 个字节(例如带标点符号的英文)或 2 个字节(如果您知道没有表情符号、中文、日文等)。 )。如果您对文本多次运行算法,则预处理的优势会更加突出。否则,每次运行算法时都会有一堆分支(尽管如果使用的符号导致可预测的分支,那么 CPU 的分支检测器会很有帮助)。我并没有说预处理更好,只是它可以并且需要测试。
如果您希望对当今非常流行的表情符号进行编码,则使用固定长度数组时所需的最小字节数为 6。在我自己的编码中,我发现根本不需要使用定长数组进行编程。无论您尝试做什么,都可以使用面向字节的编程或通过扫描 UTF-8 字节获取实际字符长度来实现。
N
Nikita Zlobin

仅考虑技术限制 - 按照当前的 UTF8 编码方案,最多可以有 7 个字节。根据它 - 如果第一个字节不是自给自足的 ASCII 字符,则它应该具有模式:1(n)0X(7-n),其中 n <= 7。

理论上它也可以是 8,但是第一个字节根本没有零位。虽然其他方面,如与前导不同的连续字节,仍然存在(允许错误检测),但我听说字节 11111111 可能是无效的,但我不能确定这一点。

最大 4 字节的限制最有可能与 UTF-16 兼容,我倾向于认为这是一个遗留问题,因为它唯一擅长的质量是处理速度,但前提是字符串字节顺序匹配(即我们在 BOM 中读取 0xFEFF )。