我在某处读到(改写):
如果我们比较一个UTF-8编码的文件和一个UTF-16编码的文件,有时,UTF-8文件的文件大小可能会大50%到100%
我是否可以说这篇文章是错误的,因为在任何时候,以UTF-8编码的文本将永远不会给我们超过+50%的文件大小的相同文本以UTF-16编码?
答案是,在UTF-8中,ASCII仅为1字节,但通常情况下,大多数西方语言(包括英语)在这里和那里使用一些需要2字节的字符,因此实际百分比各不相同。当使用UTF-8编码时,希腊语和西里尔语在其脚本中每个字符都至少需要2字节。
普通东方语言的字符在UTF-8中需要3个字节,而在UTF-16中需要2个字节。但是请注意,"不常见"的东部字符在UTF-8和UTF-16中都需要4个字节。
3确实只比2大50%。但这只适用于单个代码点。它不适用于整个文件。
实际的百分比是不可能精确地声明的,因为您不知道代码的平衡是在1字节或2字节的UTF-8范围内,还是在4字节的UTF-8范围内。如果在亚洲文本中有空白,那么它只有一个字节的UTF-8,然而它是一个昂贵的2字节的UTF-16。
这些事情确实各不相同。你只能在精确的文本上得到精确的数字,而不是一般的文本。亚洲文本中的代码点使用UTF-8的1、2、3或4个字节,而在UTF-16中,它们分别需要2或4个字节。
<标题>案例研究比较不同语言的维基百科关于东京的页面,看看我的意思。即使在东方语言中,也有大量的ASCII码。仅这一点就会使你的数据波动。考虑:
Paras Lines Words Graphs Chars UTF16 UTF8 8:16 16:8 Language
519 1525 6300 43120 43147 86296 44023 51% 196% English
343 728 1202 8623 8650 17302 9173 53% 189% Welsh
541 1722 9013 57377 57404 114810 59345 52% 193% Spanish
529 1712 9690 63871 63898 127798 67016 52% 191% French
321 837 2442 18999 19026 38054 21148 56% 180% Hungarian
202 464 976 7140 7167 14336 11848 83% 121% Greek
348 937 2938 21439 21467 42936 36585 85% 117% Russian
355 788 613 6439 6466 12934 13754 106% 94% Chinese, simplified
209 419 243 2163 2190 4382 3331 76% 132% Chinese, traditional
461 1127 1030 25341 25368 50738 65636 129% 77% Japanese
410 925 2955 13942 13969 27940 29561 106% 95% Korean
这些都是东京维基百科页面保存为文本,而不是保存为HTML。所有文本都在NFC中,而不是在NFD中。每一列的含义如下:
- 段落是空白分隔的文本跨度的数目。
- Lines是文本跨距的换行数。
- Words是由空格分隔的文本的数目。
- Graphs是Unicode扩展字形簇(有时称为字形)的数目。这些是用户可见的字符。
- 字符是Unicode码位的数目。这些是,或者应该是,程序员可见的字符。
- UTF16是文件以UTF-16格式存储时占用的字节数。
- UTF8是文件以UTF-8存储时占用的字节数。
- 8:16是UTF-8大小与UTF-16大小的比例,以百分比表示。
- 16:8是UTF-16和UTF-8的比例,以百分比表示。
- 语言是我们在这里谈论的东京页面的版本。
我把这些语言分为西方拉丁语、西方非拉丁语和东方。观察:
使用拉丁字母的西方语言在从UTF-8转换到UTF-16时遭受了严重的损失,英语遭受的损失最大,扩展了96%,匈牙利语最小,扩展了80%。
不使用拉丁字母的西方语言仍然受到影响,但只有15-20%。
东方语言在UTF-8中不受的影响,就像每个人都声称的那样!注意:
- 在韩语和(简体)中文中,UTF-8只比UTF-16大6%。
- 在日语中,UTF-8只比UTF-16大29%。
- 繁体中文在UTF-8中比在UTF-16中变小了 !事实上,在这个示例中,使用UTF-16比使用UTF-8要花费32%的成本。如果您查看Lines和Words列,就会发现这可能是由于空白使用造成的。
是的,你是正确的。代码点范围在U+0800..U+FFFF给出了+50%的大小。
UTF-8 UTF-16
U+0000..U+007F 1 2
U+0080..U+07FF 2 2
U+0800..U+FFFF 3 2
U+010000..U+10FFFF 4 4
在UTF-8中,从0到127的每个码点都存储在单个字节中。只有128及以上的代码点使用2,3存储,实际上最多使用6个字节。
虽然UTF-8字符可能使用多达4个字节(理论上可能更多),但它不用于基本多语言平面,包括"几乎所有现代语言"。
基本多语言平面的其余部分需要三个字节(它包含了几乎所有常用的字符)。Unicode的其他平面的字符需要4个字节,其中包括不太常见的CJK字符和各种历史脚本。
所以我猜100%的开销,虽然理论上是可能的,但对于典型的现代语言来说是不可能的。你必须使用补充多语言平面中的一些特殊的东西,它在UTF-8中使用4个字节,来实现这一点。
对于HTML文档或混合文本,可能没有必要切换到UTF-16以节省空间:
字符U+0800到U+FFFF在UTF-8中使用三个字节,但在UTF-16中只使用两个字节。因此,(例如)中文、日文或印地文的文本在UTF-8中,如果这些字符多于ASCII字符,就会占用更多的空间。这种情况发生在纯文本中,但很少发生在HTML文档中。例如,维基百科上的日文UTF-8和印地文Unicode文章,如果保存为UTF-16,会比原始的UTF-8版本占用更多的空间。
参见维基百科上UTF-8和UTF-16的比较。
Joel Spolsky写了一篇很棒的关于Unicode的文章,我真的可以推荐它:
每个软件开发人员绝对,肯定必须了解Unicode和字符集的绝对最低限度(没有借口!)
如果你有一个字节的字符,并添加第二个字节,我认为这是100%的增长,而不是50%。我想这就是作者的意思。
如果我写X
字符与N
字节/字符到一个文件,我将有NX
字节在该文件。因此,您可以看到,每个字符的字节数增加一倍或三倍将对文件大小产生线性影响。