How many bytes does one Unicode character take?
我对编码有点困惑。据我所知,旧的ASCII字符每字符占用一个字节。Unicode字符需要多少字节?
我假设一个Unicode字符可以包含任何语言的每个可能的字符-对吗?那么每个字符需要多少字节呢?
utf-7、utf-6、utf-16等是什么意思?它们是不同版本的Unicode吗?
我读了维基百科关于Unicode的文章,但这对我来说相当困难。我期待着看到一个简单的答案。
奇怪的是,没有人指出如何计算一个Unicode字符占用了多少字节。以下是UTF-8编码字符串的规则:
1 2 3 4 5 6 | Binary Hex Comments 0xxxxxxx 0x00..0x7F Only byte of a 1-byte character encoding 10xxxxxx 0x80..0xBF Continuation bytes (1-3 continuation bytes) 110xxxxx 0xC0..0xDF First byte of a 2-byte character encoding 1110xxxx 0xE0..0xEF First byte of a 3-byte character encoding 11110xxx 0xF0..0xF4 First byte of a 4-byte character encoding |
所以快速的答案是:它需要1到4个字节,这取决于第一个字节,它将指示它将占用多少字节。
更新正如prewett指出的,这条规则只适用于utf-8
你不会看到一个简单的答案,因为没有。
首先,Unicode不包含"每种语言的每一个字符",尽管它确实尝试过。
Unicode本身是一个映射,它定义代码点,代码点是一个数字,通常与字符关联。我说通常是因为有组合字符这样的概念。你可能会熟悉一些东西,比如重音或变音。这些字符可以与另一个字符一起使用,如
为了在计算系统中有用,我们需要为这些信息选择一种表示。这些是各种各样的Unicode编码,如utf-8、utf-16le、utf-32等,它们的主要区别在于代码单元的大小。UTF-32是最简单的编码,它有一个32位的代码单元,这意味着一个单独的代码点可以很容易地适应一个代码单元。其他编码会有这样的情况:一个代码点需要多个代码单元,或者特定的代码点根本无法在编码中表示(这是UCS-2的一个问题)。
由于组合字符的灵活性,即使在给定的编码中,每个字符的字节数也可能根据字符和规范化形式而变化。这是一种处理具有多个表示形式的字符的协议(您可以说
我知道这个问题很老,已经有了一个公认的答案,但我想举几个例子(希望它对某人有用)。
As far as I know old ASCII characters took one byte per character.
正确的。实际上,由于ASCII是7位编码,它支持128个代码(其中95个是可打印的),所以它只使用半字节(如果这有任何意义的话)。
How many bytes does a Unicode character require?
Unicode只是将字符映射到代码点。它没有定义如何编码它们。文本文件不包含Unicode字符,但可以表示Unicode字符的字节/八位字节。
I assume that one Unicode character can contain every possible
character from any language - am I correct?
不,但差不多。所以基本上是的。但仍然没有。
So how many bytes does it need per character?
和第二个问题一样。
And what do UTF-7, UTF-6, UTF-16 etc mean? Are they some kind Unicode
versions?
不,这些是编码。它们定义字节/八位字节应如何表示Unicode字符。
几个例子。如果浏览器中无法显示其中的某些内容(可能是因为字体不支持),请转到
- U+0061拉丁文小写字母A:
a 。- 不:97
- UTF-8:61
- UTF 16:00 61
- U+00A9版权标志:
? 。- 不:169
- UTF-8:C2-A9
- UTF 16:00 A9
- U+00AE注册标志:
? 。- 不:174
- UTF-8:C2-AE
- UTF 16:00 AE
- U+1337埃塞俄比亚文音节Phwa:
? - 不:4919
- UTF-8:E1 8C B7
- UTF 16:13 37
- U+2014 Em Dash:
— 。- 不:8212
- UTF-8:E2 80 94
- UTF 16:20 14
- U+2030/mile标志:
‰ 。- 不:8240
- UTF-8:E2 80 B0
- UTF 16:20 30
- U+20AC欧洲标志:
€ 。- 不:8364
- UTF-8:E2 82 AC
- 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-9A9B
- 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+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
好吧,我快疯了…
有趣的事实:
- 如果要查找特定字符,可以将其复制并粘贴到http://codepoints.net/上。
- 我在这个无用的清单上浪费了很多时间(但它已经排序了!).
- MySQL有一个称为"utf8"的字符集,它实际上不支持超过3个字节的字符。所以不能插入一堆poo,字段将被自动截断。改为使用"utf8mb4"。
- 这里有一个雪人测试页面(unicodesnowmanforyou.com)。
简而言之,
现在您需要使用字节来表示这个代码点,称为
在UTF-8中:
1 2 3 4 | 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中:
1 2 | 2 bytes: 0 - D7FF (multilingual plane except the top 1792 and private-use ) 4 bytes: D800 - 10FFFF |
在UTF 32中:
1 | 4 bytes: 0 - 10FFFF |
根据定义,10ffff是最后一个Unicode码位,它是这样定义的,因为它是UTF-16的技术限制。
它也是最大的代码点utf-8可以4字节编码,但是utf-8编码背后的思想也适用于5和6字节的编码,以覆盖代码点,直到7fffffff,也就是utf-32可以编码的一半。
在Unicode中,答案不容易给出。正如你已经指出的,问题在于编码。
对于任何没有发音字符的英语句子,utf-8的答案将和字符一样多,而对于utf-16,答案将是字符数乘以2。
唯一可以对大小进行语句的编码是utf-32。在这里,每个字符总是32位,即使我认为代码点已经为未来的UTF-64做好了准备。
最困难的至少有两件事:
- 给出的一个很好的例子是欧元字符(代码点
U+20AC 可以表示为三字节序列E2 82 AC 或四字节序列F0 82 82 AC 。 - 这两种方法都是有效的,这说明了当讨论"unicode"而不是特定的unicode编码(如utf-8或utf-16)时,答案有多复杂。
有一个很好的工具可以用utf-8计算任何字符串的字节:http://mothereff.in/byte-counter
更新:@mathias已将代码公开:https://github.com/mathiasbynens/mothereff.in/blob/master/byte-counter/eff.js
好吧,我刚刚在维基百科上找到了这个页面,在介绍部分,我看到了"Unicode可以通过不同的字符编码实现"。最常用的编码是utf-8(它对任何ASCII字符使用一个字节,在utf-8和ASCII编码中具有相同的代码值,对其他字符最多使用四个字节),现在已经过时的ucs-2(每个字符使用两个字节,但不能对当前Unicode标准中的每个字符进行编码)。
正如这句话所表明的,您的问题在于您假设Unicode是一种单一的字符编码方式。实际上有多种形式的Unicode,而且,在该引号中,其中一种甚至每个字符有一个字节,就像您习惯的那样。
所以你想要的简单答案是它是不同的。
对于UTF-16,如果字符以0xD800或更大的字符开头,则需要四个字节(两个代码单位);这样的字符称为"代理"
检查这个Unicode代码转换器。例如,输入