检查 UTF-16 和 UTF-8 的属性,我找不到任何理由更喜欢 UTF-16。
但是,检查 Java 和 C#,它看起来像那里的字符串和字符默认为 UTF-16。我在想这可能是出于历史原因,或者可能是出于性能原因,但找不到任何信息。
任何人都知道为什么这些语言选择 UTF-16?我也有任何正当理由这样做吗?
编辑:同时我也找到了这个答案,它看起来很相关并且有一些有趣的链接。
与 UTF-8(通常需要 3 个字节)相比,东亚语言在 UTF-16 中通常需要更少的存储空间(2 个字节足以存储 99% 的东亚语言字符)。
当然,对于西方语言,UTF-8 通常更小(1 个字节而不是 2 个)。对于像 HTML 这样的混合文件(其中有很多标记),这非常重要。
处理用户模式应用程序的 UTF-16比处理 UTF-8稍微容易一些,因为代理对的行为方式与组合字符的行为方式几乎相同。所以 UTF-16 通常可以作为固定大小的编码来处理。
@Oak:评论太长了......
我不了解 C#(并且会感到非常惊讶:这意味着他们只是复制了太多 Java ),但对于 Java,这很简单:Java 是在 Unicode 3.1 出现之前构思的。
因此,少于 65537 个代码点,因此每个 Unicode 代码点仍然适合 16 位,因此 Java char诞生了。
当然,这导致了今天仍然影响 Java 程序员(比如我)的疯狂问题,你有一个charAt方法,在某些情况下它既不返回 Unicode 字符也不返回 Unicode 代码点和一个方法(在 Java 5 中添加)codePointAt接受一个参数,它不是您想要跳过的代码点数!(您必须向codePointAt提供要跳过的 Java字符数,这使其成为 String 类中最不被理解的方法之一)。
所以,是的,这对大多数 Java 程序员来说绝对是疯狂和困惑的(大多数人甚至没有意识到这些问题),是的,这是出于历史原因。至少,这是人们在这个问题后发疯的借口:但这是因为 Unicode 3.1 还没有出来。
:)
我想象使用 UTF-16 的 C# 源自内部使用 UTF-16 的 Windows NT 系列操作系统。
我想 Windows NT 在内部使用 UTF-16 有两个主要原因:
与其他人的回答相反-您不能将 UTF-16 视为UCS-2。如果要正确迭代字符串中的实际字符,则必须使用 unicode 友好的迭代函数。例如,在 C# 中,您需要使用StringInfo.GetTextElementEnumerator()
.
有关更多信息,wiki 上的此页面值得一读:http ://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings
这取决于预期的字符集。如果您希望大量使用 7 位 ASCII 范围之外的 Unicode 代码点,那么您可能会发现 UTF-16 比 UTF-8 更紧凑,因为某些 UTF-8 序列的长度超过两个字节。
此外,出于效率原因,Java 和 C# 在索引字符串时不会考虑代理对。当使用由占用奇数字节的 UTF-8 序列表示的代码点时,这将完全崩溃。
UTF-16 可以更有效地表示某些语言中的字符,例如中文、日语和韩语,其中大多数字符可以用一个 16 位字表示。一些很少使用的字符可能需要两个 16 位字。UTF-8 通常在表示来自西欧字符集的字符时效率更高 - UTF-8 和 ASCII 在 ASCII 范围 (0-127) 上是等效的 - 但对于亚洲语言来说效率较低,需要三个或四个字节来表示字符可以用 UTF-16 中的两个字节表示。
UTF-16 作为 Java/C# 的内存格式具有优势,因为基本多语言平面中的每个字符都可以用 16 位表示(参见 Joe 的回答)和 UTF-16 的一些缺点(例如,混淆代码依赖在 \0 终止符上)不太相关。
如果我们只讨论纯文本,UTF-16 在某些语言中可能更紧凑,日语(约 20%)和中文(约 40%)是最好的例子。当您比较 HTML 文档时,优势完全相反,因为 UTF-16 会为每个 ASCII 字符浪费一个字节。
至于简单性或效率:如果您在编辑器应用程序中正确实现 Unicode,复杂性将是相似的,因为 UTF-16 并不总是将代码点编码为单个数字,并且单个代码点通常不是分割文本的正确方法。
鉴于在最常见的应用程序中,UTF-16 不那么紧凑,并且实现起来同样复杂,因此选择 UTF-16 而不是 UTF-8 的唯一原因是,如果您有一个完全封闭的生态系统,您会定期存储或传输纯文本完全在复杂的书写系统中,没有压缩。
用zstd或LZMA2压缩后,即使是100%的中文纯文本,优势也被完全抹杀;使用 gzip,UTF-16 在中文文本上的优势约为 4%,具有大约 3000 个独特的字素。
对于许多(大多数?)应用程序,您将只处理Basic Multilingual Plane中的字符,因此可以将 UTF-16 视为固定长度编码。
因此,您避免了 UTF-8 等可变长度编码的所有复杂性。