UTF-16有什么意义?

dsi*_*cha 64 utf-8 utf-16 utf character-encoding utf-32

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

Mat*_*lia 48

当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转换都会引起一些减速).


编辑

维基百科解释说,即使对于Java,它也是以同样的方式:它最初支持UCS-2,但在J2SE 5.0中转移到UTF-16.

所以,一般来说,当你看到某些API/Framework中使用的UTF-16时,它是因为它以UCS-2开头(为了避免字符串管理算法中的复杂性),但它转移到UTF-16以支持外部的代码点BMP,仍然保持相同的代码单元大小.


小智 19

除了向后兼容性回复之外,没有任何表明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字节)字符的优化代码检查标志为真的字符串.

空间效率怎么样?

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

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

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

  • 请参阅 https://utf8everywhere.org/。即使在最坏的情况下,UTF-16 也只能节省 20%。如果存储空间对您很重要,您应该使用实际的压缩算法,而不是用它来借口您糟糕的编码算法。在绝大多数情况下,您将使用 XML/HTML、JSON 或 Markdown 等标记语言来格式化您的内容,所有这些语言都在 ASCII 上运行。 (5认同)
  • “除了非常“专业”的文本之外,count(B) 很可能远远超过 count(A)。” 大多数东亚国家可能不同意,因为他们的大多数语言都属于 3 字节 UTF-8。 (3认同)

Eri*_*rik 5

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

  • @Erik - 你也可以说 UTF-8 实际上是每个字符一个字节......除非你需要 ASCII 之外的稀有字符。实际上,UTF-16 与 UTF-8 一样长度可变。 (24认同)
  • UTF-8 用单个单位覆盖整个 ASCII - 因此,除非您需要较稀有的字符,否则 UTF-8 实际上每个字符 1 个字节,而不是可变长度。 (2认同)