提问人:nan 提问时间:3/13/2011 最后编辑:Isaac D. Cohennan 更新时间:11/11/2023 访问量:376886
一个 Unicode 字符需要多少个字节?
How many bytes does one Unicode character take?
问:
我对编码有点困惑。据我所知,旧的 ASCII 字符每个字符占用一个字节。Unicode 字符需要多少个字节?
我假设一个 Unicode 字符可以包含来自任何语言的所有可能字符 - 我说得对吗?那么每个字符需要多少字节呢?
UTF-7、UTF-6、UTF-16 等是什么意思?它们是 Unicode 的不同版本吗?
我阅读了有关Unicode的维基百科文章,但这对我来说非常困难。我期待看到一个简单的答案。
答:
好吧,我也刚刚在上面拉起了维基百科页面,在介绍部分,我看到“Unicode可以通过不同的字符编码来实现。最常用的编码是 UTF-8(它对任何 ASCII 字符使用一个字节,在 UTF-8 和 ASCII 编码中具有相同的代码值,对于其他字符最多四个字节),现已过时的 UCS-2(每个字符使用两个字节,但不能对当前 Unicode 标准中的每个字符进行编码)”
正如这句话所表明的,你的问题是你假设Unicode是一种单一的字符编码方式。实际上有多种形式的 Unicode,同样,在引号中,其中一种甚至每个字符有 1 个字节,就像您习惯的那样。
所以你想要的简单答案是它各不相同。
在Unicode中,答案并不容易给出。正如您已经指出的那样,问题在于编码。
给定任何没有变音符号字符的英语句子,UTF-8 的答案将与字符数一样多,而 UTF-16 的答案将是字符数乘以 2。
(截至目前)我们可以对大小做出声明的唯一编码是 UTF-32。在那里,它总是每个字符 32 位,尽管我认为代码点是为未来的 UTF-64 :)准备的
让它如此困难的原因至少有两点:
- 组合字符,其中用户决定将重音符号和基本字符 ('A) 组合在一起,而不是使用已重音/变音符号 (À) 的字符实体。
- 代码点。码位是 UTF 编码允许编码超过赋予它们名称通常允许的位数的方法。例如,UTF-8 指定某些字节,这些字节本身是无效的,但是当后面跟着一个有效的延续字节时,将允许描述超出 0..255 的 8 位范围的字符。请参阅下面关于 UTF-8 的 Wikipedia 文章中的示例和超长编码。
- 这里给出的一个很好的例子是 € 字符(码位可以表示为三字节序列或四字节序列。
U+20AC
E2 82 AC
F0 82 82 AC
两者都是有效的,这表明在谈论“Unicode”而不是 Unicode 的特定编码(例如 UTF-8 或 UTF-16)时,答案是多么复杂。严格来说,正如评论中指出的那样,情况似乎不再如此,甚至是基于我的误解。更新后的维基百科文章的引文如下: 较长的编码称为超长编码,并且不是码位的有效 UTF-8 表示形式。
- 这里给出的一个很好的例子是 € 字符(码位可以表示为三字节序列或四字节序列。
评论
简单地说,这是一个标准,它为世界上所有字符分配一个数字(称为代码点)(它仍在进行中)。Unicode
现在你需要用字节来表示这个码位,这称为 . 是表示这些字符的方式。character encoding
UTF-8, UTF-16, UTF-6
UTF-8
是多字节字符编码。字符可以有 1 到 6 个字节(其中一些现在可能不需要)。
UTF-32
每个字符有 4 个字节的字符。
UTF-16
每个字符使用 16 位,它仅表示称为 BMP 的 Unicode 字符的一部分(对于所有实际目的来说,这就足够了)。Java 在其字符串中使用这种编码。
评论
你不会看到一个简单的答案,因为没有答案。
首先,Unicode 不包含“来自每种语言的每个字符”,尽管它确实尝试过。
Unicode本身就是一个映射,它定义了代码点,而代码点是一个数字,通常与一个字符相关联。我说通常是因为有组合字符之类的概念。您可能熟悉口音或变音符号等内容。它们可以与另一个字符一起使用,例如 an 或 a 来创建新的逻辑字符。因此,一个字符可以由 1 个或多个代码点组成。a
u
为了在计算系统中有用,我们需要为这些信息选择一种表示形式。这些是各种 unicode 编码,例如 utf-8、utf-16le、utf-32 等。它们的区别主要在于其代码单元的大小。UTF-32 是最简单的编码,它的代码单元为 32 位,这意味着单个代码点可以舒适地放入代码单元中。其他编码将出现以下情况:一个代码点需要多个代码单元,或者该特定代码点根本无法在编码中表示(例如,UCS-2 存在问题)。
由于组合字符的灵活性,即使在给定的编码中,每个字符的字节数也会因字符和规范化形式而异。这是一种用于处理具有多个表示形式的字符的协议(您可以说哪个是 2 个代码点,其中一个是组合字符或哪个是一个代码点)。"an 'a' with an accent"
"accented 'a'"
评论
é
["0065", "0301"]
有一个很棒的工具可以计算 UTF-8 中任何字符串的字节: http://mothereff.in/byte-counter
更新:@mathias已公开代码:https://github.com/mathiasbynens/mothereff.in/blob/master/byte-counter/eff.js
看看这个Unicode代码转换器。例如,在“0x... 表示法”字段中输入 ,其中 2009 是薄空间的 Unicode 数字,然后单击“转换”。十六进制数(3 个字节)显示在“UTF-8 代码单元”字段中。0x2009
E2 80 89
我知道这个问题很老,已经有了一个公认的答案,但我想提供一些例子(希望它对某人有用)。
据我所知,旧的 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
- 车次: 97
- UTF-8:61 个
- UTF-16:00 61
- U+0061 拉丁文小写字母 A:
- U+00A9 版权标志:
©
- 车次: 169
- UTF-8:C2 A9
- UTF-16:00 A9
- U+00AE注册标志:
®
- 车次: 174
- UTF-8:C2 AE
- UTF-16:00 自动曝光
- U+00A9 版权标志:
- U+1337 埃塞俄比亚语音节 PHWA:
ጷ
- 编号: 4919
- UTF-8:E1 8C B7
- UTF-16:13 37
- U+2014 EM 短跑:
—
- 车次: 8212
- UTF-8:E2 80 94
- UTF-16:20 14
- U+2030 每千个标志:
‰
- 车次: 8240
- UTF-8:E2 80 B0
- UTF-16:20 30
- U+20AC 欧元符号:
€
- 车次: 8364
- UTF-8:E2 82 交流
- UTF-16:20 交流电
- U+2122 商标标志:
™
- 编号: 8482
- UTF-8:E2 84 A2
- UTF-16:21 22
- U+2603 雪人:
☃
- 车次: 9731
- UTF-8:E2 98 83
- UTF-16:26 03
- U+260E 黑色电话:
☎
- 车次: 9742
- UTF-8:E2 98 8E
- UTF-16:26 0E
- U+2614 雨伞:
☔
- 编号: 9748
- UTF-8:E2 98 94
- UTF-16:26 14
- U+263A 白色笑脸:
☺
- 车次: 9786
- UTF-8:E2 98 BA
- UTF-16:26 个 3A
- U+2691 黑旗:
⚑
- 车次: 9873
- UTF-8:E2 9A 91
- UTF-16:26 91
- U+269B 原子符号:
⚛
- 车次: 9883
- UTF-8:E2 9A 9B
- UTF-16:26 9B
- U+2708飞机:
✈
- 编号: 9992
- UTF-8:E2 9C 88
- UTF-16:27 08
- U+271E 阴影白色拉丁十字架:
✞
- 编号: 10014
- UTF-8:E2 9C 9E
- UTF-16:27 1E
- U+3020 邮政标记正面:
〠
- 车次: 12320
- UTF-8:E3 80 A0
- UTF-16:30 20
- U+8089 CJK统一表意文字-8089:
肉
- 车次: 32905
- UTF-8:E8 82 89
- UTF-16:80 89
- U+1337 埃塞俄比亚语音节 PHWA:
- U+1F4A9 一堆便便:
💩
- 车次: 128169
- UTF-8:F0 9F 92 A9
- UTF-16:D8 3D DC A9
- U+1F680火箭:
🚀
- 车次: 128640
- UTF-8:F0 9F 9A 80
- UTF-16:D8 3D DE 80
- U+1F4A9 一堆便便:
好吧,我得意忘形了......
趣闻:
- 如果您正在寻找特定角色,可以将其复制并粘贴到 http://codepoints.net/ 上。
- 我在这个无用的清单上浪费了很多时间(但它已经排序了!
- MySQL有一个名为“utf8”的字符集,它实际上不支持长度超过3个字节的字符。所以你不能插入一堆便便,字段会被默默截断。请改用“utf8mb4”。
- 有一个雪人测试页面(unicodesnowmanforyou.com)。
评论
00A9
00 A9
奇怪的是,没有人指出如何计算一个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 个字节,具体取决于第一个字节,这将指示它将占用多少字节。
评论
对于 UTF-16,如果字符以 0xD800 或更大开头,则需要四个字节(两个代码单元);这样的角色被称为“代理对”。更具体地说,代理对的形式为:
[0xD800 - 0xDBFF] [0xDC00 - 0xDFF]
其中 [...] 表示具有给定范围的双字节代码单元。任何 <= 0xD7FF 都是一个代码单元(两个字节)。任何 >= 0xE000 都是无效的(可以说,BOM 标记除外)。
参见 http://unicodebook.readthedocs.io/unicode_encodings.html,第 7.5 节。
在 Unicode 中,每个字符都由一个从 0 到 0x10FFFF 的整数表示。在 32 位整数中天真地执行此操作称为 UTF-32 编码。为了减少浪费,UTF-8 和 UTF-16 是需要较少空间的编码,用于较低的代码点。
请注意,在实现中所谓的 UTF-16 通常实际上只是 UCS2:UTF-16 可以容纳 32 位的代码点子集。
存储要求如下。
在 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 字节编码,以覆盖码位直到 7FFFFFFFF,即。UTF-32 的一半。
来自维基:
UTF-8,一种 8 位可变宽度编码,可最大限度地兼容 ASCII;
UTF-16,一种 16 位可变宽度编码;
UTF-32,一种 32 位固定宽度编码。
这是三种最流行的不同编码。
- 在 UTF-8 中,每个字符被编码为 1 到 4 个字节(主要编码)
- 在 UTF16 中,每个字符被编码为 1 到 2 个 16 位字和
- 在 UTF-32 中,每个字符都编码为单个 32 位字。
Unicode
是一个标准,它为每个字符提供唯一的编号。这些唯一的数字被称为 s(这只是唯一的代码)世界上存在的所有字符(有些字符仍有待添加)。code point
出于不同的目的,您可能需要用字节来表示(大多数编程语言都这样做),这就是发挥作用的地方。code points
Character Encoding
UTF-8
、 等都是 ,Unicode 的码位以不同的方式在这些编码中表示。UTF-16
UTF-32
Character Encodings
UTF-8
编码具有可变宽度的长度,其中编码的字符可以占用 1 到 4 个字节(包括 1 到 4 个字节);
UTF-16
具有可变长度,其中编码的字符可以采用 1 或 2 个字节(即 8 位或 16 位)。这只代表了所有称为BMP(基本多语言平面)的Unicode字符的一部分,对于几乎所有情况来说都足够了。Java 对其字符串和字符使用编码;UTF-16
UTF-32
具有固定长度,每个字符正好占用 4 个字节(32 位)。
下一个:深拷贝和浅拷贝有什么区别?
评论