ChatGPT解决这个技术问题 Extra ChatGPT

一个 Unicode 字符占用多少字节?

我对编码有点困惑。据我所知,旧的 ASCII 字符每个字符占用一个字节。一个 Unicode 字符需要多少字节?

我假设一个 Unicode 字符可以包含来自任何语言的所有可能字符 - 我正确吗?那么每个字符需要多少字节呢?

UTF-7、UTF-6、UTF-16 等是什么意思?它们是不同版本的 Unicode 吗?

我阅读了Wikipedia article about Unicode,但这对我来说非常困难。我期待看到一个简单的答案。

抱歉,没有简单的答案。我觉得整个事情有点乱。 Unicode 被宣传为使用两个字节并能够表示所有字符,但事实证明两个字节还不够。
“简单答案”:一个 unicode 字符占用 1-4 个字节。 Unicode 涵盖了很多语言,但不是全部。上次我查看时,例如克林贡语不是官方的 Unicode 字符集。
克林贡语不是 Unicode 标准本身的一部分,不是。它改用 Uniode 的私人使用区 (U+F8D0 - U+F8FF)。
救世主问题-谢谢。我的情况是通过符合 SCORM 1.2 的 LMS 存储数据...... SCORM 1.2 'cmi.suspend_data' 的标准是 4096 字节的数据,之前的开发人员认为这意味着我们可以存储 4096 个字符。哦,伙计,他错了——我刚刚发现了为什么我们的书签在长课程上失败了。所以现在我知道,因为我们使用的是 UTF-8,所以每个字符需要 4 个字节,给我们 1024 个字符。

t
tambre

奇怪的是,没有人指出如何计算一个 Unicode 字符占用多少字节。以下是 UTF-8 编码字符串的规则:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

所以快速回答是:它需要 1 到 4 个字节,具体取决于第一个字节,它将指示它将占用多少字节。


我相信 4 字节字符的最大十六进制值是 0xF7(不是 0xF4)。
太感谢了!我只是通过IETF标准控制+f'ing,我没有找到任何关于编码的内容,我正在阅读的文章没有足够详细地说明使用多少位来表示尾随代码的数量每个“字符”的点数。
这现在在我的“新团队成员介绍”备忘单的第二页上,还有搞笑的前两条评论
0xF4 不是错误,而是澄清。 Unicode 代码点在 0-0x10ffff 范围内,因此最后一个代码点被编码为 F4 8F BF BF。
@DJPJ 原则上您是正确的,但 UTF-8 并未使用所有可用空间,以与 UTF-16 兼容。
M
Mazdak

你不会看到一个简单的答案,因为没有答案。

首先,Unicode 不包含“来自每种语言的每个字符”,尽管它确实会尝试。

Unicode 本身是一种映射,它定义了代码点,而代码点是一个数字,与 通常 一个字符相关联。我说通常是因为有组合字符之类的概念。您可能熟悉口音或变音符号等内容。它们可以与另一个字符(例如 au)一起使用以创建新的逻辑字符。因此,一个字符可以包含 1 个或多个代码点。

为了在计算系统中有用,我们需要为这些信息选择一个表示。这些是各种 unicode 编码,例如 utf-8、utf-16le、utf-32 等。它们的区别主要在于其代码单元的大小。 UTF-32 是最简单的编码,它有一个 32 位的代码单元,这意味着一个单独的代码点可以轻松地融入一个代码单元。其他编码会出现一个代码点需要多个代码单元的情况,或者该特定代码点根本无法在编码中表示(这是 UCS-2 的一个问题)。

由于组合字符的灵活性,即使在给定的编码中,每个字符的字节数也会根据字符和规范化形式而有所不同。这是一种用于处理具有多个表示形式的字符的协议(您可以说 "an 'a' with an accent" 是 2 个代码点,其中一个是组合字符或 "accented 'a'" 是一个代码点)。


好的。那么在一个给定的代码点中表示一个给定的字符需要多少字节?例如,不间断的空间。
当涉及到在 UTF8 数组上编写 strlen()、substr() 和其他字符串操作函数时,组合字符使程序员的生活变得一团糟。这种工作永远不会完成,而且总是有问题。
我编写了一个演示,展示了使用每种编码解释的 Windows-1252、UTF8 和 UTF8-BOM 编码文件,并比较了结果之间的相等性:github.com/vladyrn/encodings_demo
b
basic6

我知道这个问题很老,并且已经有一个公认的答案,但我想提供一些例子(希望它对某人有用)。

据我所知,旧的 ASCII 字符每个字符占用一个字节。

正确的。实际上,由于 ASCII 是 7 位编码,它支持 128 个代码(其中 95 个是可打印的),所以它只使用半个字节(如果这有意义的话)。

一个 Unicode 字符需要多少字节?

Unicode 只是将字符映射到代码点。它没有定义如何对它们进行编码。文本文件不包含 Unicode 字符,而是可能表示 Unicode 字符的字节/八位字节。

我假设一个 Unicode 字符可以包含来自任何语言的所有可能字符 - 我正确吗?

不,但差不多。所以基本上是的。但还是没有。

那么每个字符需要多少字节呢?

和你的第二个问题一样。

UTF-7、UTF-6、UTF-16 等是什么意思?它们是某种 Unicode 版本吗?

不,那些是编码。它们定义字节/八位字节应如何表示 Unicode 字符。

几个例子。如果其中一些无法在您的浏览器中显示(可能是因为字体不支持它们),请转到 http://codepoints.net/U+1F6AA(将 1F6AA 替换为十六进制代码点)查看图像。

U+0061 拉丁小写字母 A:a Nº:97 UTF-8:61 UTF-16:00 61 U+00A9 版权符号:© Nº:169 UTF-8:C2 A9 UTF-16:00 A9 U+00AE 注册符号: ® Nº: 174 UTF-8: C2 AE UTF-16: 00 AE U+1337 ETHIOPIC SYLLABLE PHWA:ጷ Nº: 4919 UTF-8: E1 8C B7 UTF-16: 13 37 U+2014 EM DASH: — Nº: 8212 UTF-8: E2 80 94 UTF-16: 20 14 U+2030 PER MILLE SIGN: ‰ Nº: 8240 UTF-8: E2 80 B0 UTF-16: 20 30 U+20AC EURO SIGN: € Nº: 8364 UTF- 8:E2 82 AC UTF-16:20 AC U+2122 商标符号:™ Nº:8482 UTF-8:E2 84 A2 UTF-16:21 22 U+2603 SNOWMAN:☃ Nº:9731 UTF-8:E2 98 83 UTF-16:26 03 U+260E 黑色电话:☎ Nº:9742 UTF-8:E2 98 8E UTF-16:26 0E U+2614 雨伞:☔ Nº:9748 UTF-8:E2 98 94 UTF -16:26 14 U+263A 白色笑脸:☺ Nº:9786 UTF-8:E2 98 BA UTF-16:26 3A U+2691 BLACK FLAG:⚑ Nº:9873 UTF-8:E2 9A 91 UTF-16: 26 91 U+269B 原子符号:⚛ Nº:9883 UTF-8:E2 9A 9B UTF-16:26 9B U+2708 飞机:✈ Nº:9992 UTF-8:E2 9C 88 UTF-16:27 08 U+271E阴影白色拉丁十字:✞ Nº:10014 UTF-8:E2 9C 9E UTF-16: 27 1E U+3020 POSTAL MARK FACE: 〠 Nº: 12320 UTF-8: E3 80 A0 UTF-16: 30 20 U+8089 CJK UNIFIED IDEOGRAPH-8089: 肉 Nº: 32905 UTF-8: E8 82 89 UTF-16: 80 89 U+1F4A9 POO: 💩 Nº: 128169 UTF-8: F0 9F 92 A9 UTF-16: D8 3D DC A9 U+1F680 ROCKET: 🚀 Nº: 128640 UTF-8: F0 9F 9A 80 UTF-16:D8 3D DE 80

好吧,我走神了……

有趣的事实:

如果您正在寻找特定的字符,您可以在 http://codepoints.net/ 上复制并粘贴它。

我在这个无用的列表上浪费了很多时间(但它已经排序了!)。

MySQL 有一个名为“utf8”的字符集,它实际上不支持超过 3 个字节的字符。所以不能插入一堆便便,字段会被默默截断。请改用“utf8mb4”。

有一个雪人测试页面 (unicodesnowmanforyou.com)。


UTF-16 中的 代码单元 为 16 位宽。您向他们展示了中间的空格,这是误导性的。 © 的 UTF-16 表示应该是 00A9 而不是 00 A9(这将是 UTF-16BE)。
有什么不同? BE不代表大端吗?他是用大端写的,所以用大端 UTF-16 写的文件就和 UTF-16BE 一样,对吧?
更正: 1) ASCII 是 7 位,一个字节是 8 位,所以比一半多得多。 2) Unicode 确实定义了如何编码代码点。 UTF-8、UTF-16 和 UTF-32 在 Unicode 标准中定义。
@JonathanRosenne 我认为他/她的意思是它只使用了用 8 位表示的可能值的一半,而不是它使用了一半的位。
我真的很喜欢这些例子。例如,他们强调了为什么人们可能更喜欢 UTF-16 而不是 UTF-8。不同软件的开发人员可能会根据更可能使用的 Unicode 字符来选择不同的编码。例如,在中国/日本,UTF-16(2 字节)对他们来说比 UTF-8 更有意义,因为在 UTF-8 中编码相同的字符通常需要两倍的字节数
Z
Zimbabao

简单地说 Unicode 是一种标准,它为世界上的所有字符分配一个数字(称为代码点)(它仍在进行中)。

现在您需要使用字节来表示此代码点,即 character encodingUTF-8, UTF-16, UTF-6 是表示这些字符的方式。

UTF-8 是多字节字符编码。字符可以有 1 到 6 个字节(其中一些现在可能不需要)。

UTF-32 每个字符有 4 个字节一个字符。

UTF-16 为每个字符使用 16 位,它仅代表称为 BMP 的 Unicode 字符的一部分(对于所有实际目的来说,它就足够了)。 Java 在其字符串中使用这种编码。


Unicode 是 21 位代码集,4 个字节足以表示 UTF-8 中的任何 Unicode 字符。 UTF-16 使用代理来表示 BMP(基本多语言平面)之外的字符;它需要 2 或 4 个字节来表示任何有效的 Unicode 字符。 UCS-2 是 UTF-16 的唯一 16 位变体,不支持 BMP 之外的代理或字符。
你是对的。 UTF-8 原版有 6 个字节来容纳 32 位。我实际上不想让事情复杂化,因为他已经对 wiki doc 感到困惑 :)
这个答案指出 UTF-16 不能编码 BMP 代码点。这是不正确的,因为它们可以像使用代理对在 UTF-8 中一样进行编码。 (你一定想到过时的 UCS-2,在 Unicode 2.0 出现之前,它只编码 16 位代码点。)此外,Java 并不完全使用 UTF-16,它使用其代码点的修改形式0 的编码方式不同。
@rdb - 恰恰相反。答案说 UTF-16 代表 BMP。
我打错了;我的意思是说“非BMP”。答案中的错误是它说 UTF-16 代表 BMP 字符,这是不准确的。 UTF-16 可以编码所有 unicode 字符——非 BMP 字符通过代理对进行编码。也许回答者对 UCS-2 感到困惑。
J
John

在 UTF-8 中:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

在 UTF-16 中:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

在 UTF-32 中:

4 bytes:      0 - 10FFFF

根据定义,10FFFF 是最后一个 unicode 代码点,它是这样定义的,因为它是 UTF-16 的技术限制。

它也是 UTF-8 可以编码为 4 字节的最大代码点,但 UTF-8 编码背后的想法也适用于 5 和 6 字节编码,以覆盖直到 7FFFFFFF 的代码点,即。 UTF-32 的一半。


0
0xC0000022L

在 Unicode 中,答案并不容易给出。正如您已经指出的那样,问题在于编码。

给定任何没有变音符号的英文句子,UTF-8 的答案将是与字符一样多的字节,而对于 UTF-16,它将是字符数乘以 2。

(截至目前)我们可以声明大小的唯一编码是 UTF-32。每个字符总是 32 位,尽管我认为代码点是为未来的 UTF-64 准备的 :)

导致它如此困难的原因至少有两点:

组合字符,而不是使用已经重音/变音符号 (À) 的字符实体,用户决定将重音符号和基本字符 (`A) 结合起来。码点。代码点是 UTF-encodings 允许编码的位数超过其名称通常允许的位数的方法。例如,UTF-8 指定了某些本身无效的字节,但是当后面跟着一个有效的连续字节时,将允许描述一个超出 0..255 的 8 位范围的字符。请参阅下面有关 UTF-8 的 Wikipedia 文章中的示例和超长编码。给出的一个很好的例子是 € 字符(代码点 U+20AC 可以表示为三字节序列 E2 82 AC 或四字节序列 F0 82 82 AC。两者都是有效的,这表明答案是多么复杂当谈论“Unicode”而不是 Unicode 的特定编码时,例如 UTF-8 或 UTF-16。


N
Nic Cottrell

有一个很棒的工具可以计算 UTF-8 中任何字符串的字节数:http://mothereff.in/byte-counter

更新:@mathias 已公开代码:https://github.com/mathiasbynens/mothereff.in/blob/master/byte-counter/eff.js


L
Loduwijk

好吧,我也刚刚打开了 Wikipedia 页面,在介绍部分我看到“Unicode 可以通过不同的字符编码来实现。最常用的编码是 UTF-8(它对任何 ASCII 字符使用一个字节,它有“

正如这句话所表明的那样,您的问题是您假设 Unicode 是编码字符的单一方式。实际上有多种形式的 Unicode,同样在那个引用中,其中一种甚至每个字符有 1 个字节,就像你习惯的那样。

因此,您想要的简单答案是它会有所不同。


G
Giorgi Tsiklauri

Unicode 是一个 standard,它为每个字符提供一个唯一编号。对于世界上存在的所有字符,这些唯一的数字被称为 code point(这只是唯一的代码)(一些仍有待添加)。

出于不同的目的,您可能需要以字节表示此 code points(大多数编程语言都这样做),这就是 Character Encoding 的作用所在。

UTF-8UTF-16UTF-32 等都是 Character Encodings,而 Unicode 的代码点在这些编码中以不同的方式表示。


UTF-8 编码具有可变宽度长度,其中编码的字符可以占用 1 到 4 个字节(含);

UTF-16 具有可变长度,其中编码的字符可以占用 1 或 2 个字节(即 8 位或 16 位)。这仅代表称为 BMP(基本多语言平面)的所有 Unicode 字符的一部分,几乎适用于所有情况。 Java 对其字符串和字符使用 UTF-16 编码;

UTF-32 具有固定长度,每个字符正好占用 4 个字节(32 位)。


p
prewett

对于 UTF-16,如果字符以 0xD800 或更大开头,则需要四个字节(两个代码单元);这样的字符称为“代理对”。更具体地说,代理对具有以下形式:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

其中 [...] 表示具有给定范围的两字节代码单元。任何 <= 0xD7FF 都是一个代码单元(两个字节)。任何 >= 0xE000 都是无效的(可以说除了 BOM 标记)。

请参阅 http://unicodebook.readthedocs.io/unicode_encodings.html,第 7.5 节。


Y
Yash

看看这个Unicode code converter。例如,在“0x...表示法”字段中输入 0x2009,其中 2009 is the Unicode number for thin space,然后单击转换。十六进制数 E2 80 89(3 个字节)出现在“UTF-8 代码单元”字段中。


C
Community

来自维基:

UTF-8,一种 8 位可变宽度编码,可最大限度地与 ASCII 兼容; UTF-16,一种 16 位的可变宽度编码; UTF-32,一种 32 位、固定宽度的编码。

这是三种最流行的不同编码。

在 UTF-8 中,每个字符都被编码为 1 到 4 个字节(主要编码)

在 UTF16 中,每个字符被编码为 1 到 2 个 16 位字,并且

在 UTF-32 中,每个字符都被编码为单个 32 位字。