78

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

4

5 回答 5

59

设计 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,仍然保持相同的代码单元大小。

于 2011-03-13T20:36:38.590 回答
22

除了向后兼容的回复外,没有任何回复表明 UTF-16 优于 UTF-8。

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

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

警告 1)

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

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

如果您的代码假定所有 UTF-16 字符的长度为两个字节,并且您的程序与 BMP 之外有单个字符的应用程序或库交互,那么您的代码将中断。必须编写检查或操作 UTF-16 的代码来处理需要超过 2 个字节的 UTF-16 字符的情况;因此,我“驳回”了这个警告。

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

警告 2)

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

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

空间效率如何?

显然,对于 A) UTF-16 需要比 UTF-8 更少的字节数来编码的字符,UTF-16 更有效。

显然,对于 B) 字符,UTF-8 比 UTF-16 需要更少的字节来编码,因此 UTF-8 更有效。

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

于 2014-01-05T09:11:44.820 回答
4

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

于 2011-03-13T20:32:38.750 回答
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(not 1)。所以这是一种 hack,但事实证明字符不是可变长度的。

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

于 2011-03-13T20:48:04.297 回答
0

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

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

于 2011-03-13T20:32:40.323 回答