UTF-16的意义是什么?


72

我从不了解UTF-16编码的要点。如果您需要能够将字符串视为随机访问(即代码点与代码单元相同),则您需要UTF-32,因为UTF-16的长度仍然可变。如果您不需要它,那么与UTF-8相比,UTF-16似乎是对空间的巨大浪费。与UTF-8和UTF-32相比,UTF-16有何优势?为什么Windows和Java将其用作本机编码?


也许您可以重新表述您的问题,使其不那么主观和争论?
加布

5
如果仅对于UTF-32而言是正确的话……结合字符en.wikipedia.org/wiki/Combining_character玩5分钟,然后告诉我一切“随机”是多少:-)
xanatos

Answers:


55

当设计Windows NT时,UTF-16不存在(NT 3.51诞生于1993年,而UTF-16诞生于1996年并采用Unicode 2.0标准);取而代之的是UCS-2,当时它足以容纳Unicode中可用的每个字符,因此1个代码点= 1个代码单位等效实际上是正确的-字符串不需要可变长度逻辑。

他们后来移至UTF-16,以支持整个Unicode字符集;但是它们无法移至UTF-8或UTF-32,因为这将破坏API接口中的二进制兼容性(以及其他功能)。

至于Java,我不确定。自从它于1995年发布以来,我怀疑UTF-16已经发布了(即使尚未标准化),但我认为与基于NT的操作系统的兼容性可能在他们的选择中起到了一定作用(连续每次调用Windows API的UTF-8 <-> UTF-16转换都会导致速度降低)。


编辑

Wikipedia解释说,即使对于Java,它也以相同的方式运行:它最初支持UCS-2,但在J2SE 5.0中移至UTF-16。

因此,通常来说,当您看到某些API /框架中使用了UTF-16时,是因为它以UCS-2开头(以避免字符串管理算法中的复杂性),但是它移至UTF-16以支持外部的代码点BMP,仍保持相同的代码单元大小。


21

除了向后兼容答复之外,没有其他任何表明UTF-16优于UTF-8的答复有意义。

好吧,我的评论有两个警告。

Erik说:“ UTF-16用单个单位覆盖了整个BMP-因此,除非您需要BMP之外的稀有字符,否则UTF-16实际上是每个字符2个字节。”

注意事项1)

如果可以确定您的应用程序永远不需要BMP之外的任何字符,并且您编写供其使用的任何库代码都绝不会与任何需要BMP之外的字符的应用程序一起使用,那么您可以使用UTF-16,并编写隐式假定每个字符长度恰好为两个字节的代码。

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

如果您的代码假定所有UTF-16字符的长度均为2个字节,并且您的程序与BMP外部只有一个字符的应用程序或库进行交互,则代码将中断。必须编写检查或操作UTF-16的代码,以处理需要两个以上字节的UTF-16字符;因此,我正在“消除”这一警告。

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

警告2)

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

像这样:假设很少修改某些长字符串,但是经常对其进行检查(或者更好的是,一旦构建就永远不要修改-即,由字符串生成器创建无法修改的字符串)。可以为每个字符串设置一个标志,以指示该字符串是否仅包含“固定长度”字符(即,不包含长度不完全是两个字节的字符)。可以使用假定固定长度(2个字节)字符的优化代码来检查标志为真的字符串。

空间效率如何?

显然,对于A)字符来说,UTF-16的效率更高,因为UTF-16与UTF-8相比,其编码所需的字节数更少。

显然,对于B)字符而言,UTF-8效率更高,因为B)字符比UTF-16需要更少的字节进行编码。

除了非常“专业”的文字外,count(B)可能远远超过count(A)。


3

UTF-16用单个单位覆盖了整个BMP-因此,除非您需要BMP之外的稀有字符,否则UTF-16实际上是每个字符2个字节。UTF-32需要更多空间,UTF-8需要可变长度支持。


我将在UTF-32上添加必要的Wiki参考,以解释所有缺点:en.wikipedia.org/wiki/UTF-32/UCS-4
xanatos 2011年

16
@Erik-您最好说UTF-8实际上是每个字符一个字节...除非您需要ASCII以外的稀有字符。实际上,UTF-16和UTF-8一样可变长。
SigueSigueBen 2012年

我使用日语字符(或法语),实际上我们正在考虑使用UTF-16。我希望本次讨论的内容包括变量的可变性以及是否可以针对不同程度的非ASCII语言更好地优化使用UTF-16
Aki

1
UTF-8以单个单位覆盖整个ASCII-因此,除非需要稀有字符,否则UTF-8实际上是每个字符1个字节,而不是可变长度。
兹德涅克Pavlas

1

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

这使您两全其美,您拥有固定的字符大小,但仍然可以打印任何人都可能使用的所有字符(除正统的Klingon宗教脚本外)


8
除非它们来自香港,否则即使基本的广东话也可能要求BMP以外的字符。除此之外,没有任何乐趣可以像使程序无缘无故地拒绝最终用户看到的某些有效字符所带来的乐趣。
prosfilaes,2012年

1

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

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

与UTF-8相比,UTF-16的优势在于,如果对UTF-8使用相同的hack,则会放弃太多。


5
我认为(是的,我认为:-)),如果程序员必须知道变长字符,而不是“偶然地”发现它们,世界将会变得更好(就像现在,程序员可以活很多年而不知道代码点)可能会很长2,如果一切都是UTF-8,他只能将头埋在地下几个月:
xanatos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.