什么是UTF-16的重点?

我从来没有理解UTF-16编码的重点。 如果需要将string视为随机访问(即代码点与代码单元相同),则需要UTF-32,因为UTF-16的长度仍然是可变的。 如果你不需要这个,那么与UTF-8相比,UTF-16似乎是一个巨大的空间浪费。 UTF-16与UTF-8和UTF-32相比有什么优势?Windows和Java为什么使用它作为它们的本地编码?

当Windows NT被devise为UTF-16不存在时(NT 3.51诞生于1993年,而UTF-16于1996年诞生于Unicode 2.0标准); 相反,当时UCS-2足以容纳Unicode中的每个字符,所以1个码位= 1个码单位的等价性实际上是正确的 – string不需要可变长度的逻辑。

后来他们转移到了UTF-16,以支持整个Unicode字符集; 但是他们不能移动到UTF-8或UTF-32,因为这会破坏API接口(除此之外)的二进制兼容性。

至于Java,我不太确定。 自从它在1995年发布以来,我怀疑UTF-16已经在空中(即使它还没有被标准化),但是我认为与基于NT的操作系统的兼容性可能在他们的select中起了一定的作用对于Windows API的每次调用,UTF-8 < – > UTF-16转换可能会引起一些放缓)。


编辑

维基百科解释说,即使对于Java也是如此:它最初支持UCS-2,但在J2SE 5.0中转移到了UTF-16。

所以,一般来说当你在某些API / Framework中看到UTF-16的时候,这是因为它起始于UCS-2(为了避免stringpipe理algorithm的复杂性),但是它转移到UTF-16来支持BMP,仍然保持相同的代码单元大小。

除了向后兼容性回复之外,没有任何回复指出UTF-16比UTF-8更有优势。

那么,我的评论有两个警告。

Erik指出:“UTF-16以单一单位覆盖整个BMP – 所以除非你需要BMP以外的稀有字符,否则UTF-16每字符有效2字节。

注意事项1)

如果您可以确定您的应用程序永远不需要BMP以外的任何字符,并且您使用的任何库代码都不会用于任何需要BMP之外的字符的应用程序,那么您可以使用UTF-16编写的代码可以隐含地假设每个字符的长度都是两个字节。

这似乎非常危险(实际上是愚蠢的)。

它可能是BMP以外的单个字符,应用程序或库代码可能在某些时候需要处理,假定所有UTF-16字符长度为两个字节的代码将会中断。

因此,必须编写检查或操作UTF-16的代码来处理需要超过2个字节的UTF-16字符的情况。

因此,我“解雇”这个警告。

因此,UTF-16编码并不比UTF-8编码简单(两者的代码都必须处理可变长度的字符)。

警告2)

在某些情况下,如果编写得当,UTF-16可能在计算上更有效率。

像这样:假设某些长string很less被修改,但是经常被检查(或者更好, 从未被修改 – 即,一个string生成器创build不可修改的string)。 可以为每个string设置一个标志,指示该string是否仅包含“固定长度”字符(即,不包含长度不完全是两个字节的字符)。 标志为真的string可以使用假定为固定长度(2字节)字符的优化代码进行检查。

空间效率如何?

对于UTF-16来说,UTF-16比UTF-8需要更less的字节来编码的字符显然更有效。

对UTF-8来说,UTF-8比UTF-16需要更less的字节来编码的B)字符显然更有效率。

除了非常“专业”的文本,计数(B)可能远远超过计数(A)。

UTF-16用单个单位覆盖整个BMP – 所以除非你需要BMP以外的稀有字符,否则UTF-16每个字符有效2个字节。 UTF-32需要更多的空间,UTF-8需要可变长度的支持。

UTF16通常用作直接映射到多字节字符集,即onyl原始的0-0xFFFF分配的字符。

这给了你两个世界的最好的,你有固定的字符大小,但仍然可以打印任何人都可能使用的字符(正统的克林贡宗教脚本除外)

UTF-16允许所有的基本多语言平面(BMP)被表示为单个代码单元。 超出U + FFFF的Unicode代码点由代理对代表。

有趣的是,Java和Windows(以及其他使用UTF-16的系统)都在代码单元级而不是Unicode代码点级上运行。 所以由单个字符U + 1D122(MUSICAL SYMBOL F CLEF)组成的string在Java中被编码为“\ ud824 \ udd22”和"\ud824\udd22".length() == 2 (不是1 )。 所以这是一种黑客,但事实certificate,字符不是可变长度。

UTF-16相对于UTF-8的优势在于,如果UTF-8使用相同的破解方法,则可以放弃太多。