如果我理解正确的话,UTF-32 可以处理宇宙中的每一个字符。通过使用代理对,UTF-16 也可以。那么使用 UTF-32 而不是 UTF-16 有什么好的理由吗?
7 回答
在 UTF-32 中,一个 unicode 字符总是由 4 个字节表示,因此解析代码比 UTF-16 字符串更容易编写,因为在 UTF-16 中,一个字符由不同数量的字节表示。不利的一面是,UTF-32字符总是需要 4 个字节,如果您主要使用英文字符,这可能会很浪费。因此,它的设计选择取决于您的要求是使用 UTF-16 还是 UTF-32。
有人可能更喜欢处理 UTF-32 而不是 UTF-16,因为处理代理对几乎总是处理“特殊情况”,而必须处理这些特殊情况意味着您有可能因为您处理而出现错误的区域错误地处理它们(或者更有可能根本忘记处理它们)。
如果 UTF-32 增加的内存使用不是问题,那么降低复杂性可能足以成为选择它的优势。
这也是来自 The Unicode Consortium 的一个很好的文档。
版权所有 © 1991–2009 Unicode, Inc. Unicode 标准,版本 5.2
从表面上看,UTF-32 似乎是用于内部处理代码的 Unicode 编码形式的明显选择,因为它是一种固定宽度的编码形式。它可以与 C 和 C++ 一致地绑定
wchar_t
,这意味着这些编程语言可以提供内置支持和现成的字符串 API,程序员可以利用这些 API。但是,UTF-16 具有许多抵消优势,可能导致实施者选择它作为内部处理代码。虽然所有三种编码形式每个字符最多需要 4 个字节(或 32 位)的数据,但实际上 UTF-32 在几乎所有实际数据集的情况下占用的存储空间是 UTF-16 所需的两倍。因此,一个常见的策略是让内部字符串存储使用 UTF-16 或 UTF-8,但在处理单个字符时使用 UTF-32。UTF-32 与 UTF-16。平均而言,超过 99% 的 UTF-16 数据使用单个代码单元表示。这几乎包括软件需要通过对文本进行特殊操作来处理的所有典型字符,例如格式控制字符。因此,大多数文本扫描操作根本不需要解压缩 UTF-16 代理对,而是可以安全地将它们视为字符串的不透明部分。对于很多操作来说,UTF-16 和 UTF-32 一样容易处理,而 UTF-16 作为处理代码的性能往往相当不错。UTF-16 是大多数支持 Unicode 的实现选择的内部处理代码。除了 Unix 平台,UTF-16 提供了紧凑大小与处理 BMP 之外的偶尔字符的能力的正确组合。在软件编码设计和维护的简单性方面,UTF-32 具有一定的优势。因为字符处理是固定宽度的,UTF-32处理不需要在软件中维护分支来测试和处理UTF-16补充字符所需的双码单元元素。相反,大表中的 32 位索引并不是特别有效的内存。为了避免此类索引的大量内存损失,Unicode 表通常作为多级表处理(请参阅第 5.1 节,转码到其他标准中的“多级表”)。在这种情况下,32 位代码点值被分割成更小的范围,以允许对表进行分段访问。即使在典型的 UTF-32 实现中也是如此。UTF-32 作为处理代码的性能实际上可能比 UTF-16 对相同数据的性能更差,因为额外的内存开销意味着将更频繁地超出缓存限制并且内存分页将更频繁地发生。对于具有对 16 位对齐访问施加惩罚但具有非常大的内存的处理器设计的系统,这种影响可能不太明显。无论如何,Unicode 代码点不一定符合用户对“字符”的期望。例如,以下不是由单个代码点表示的:组合字符序列,例如 ; 用于韩语的联合 jamo 序列;或梵文连词“ksha”。因为某些 Unicode 文本处理必须知道并处理这样的字符序列作为文本元素,UTF-32 的固定宽度编码形式的优势在某种程度上被处理文本元素的固有可变宽度特性所抵消。请参阅 Unicode 技术标准 #18,“Unicode 正则表达式”,了解由于用户对“字符”身份的期望,通常实现的流程处理固有可变宽度文本元素的示例。UTF-8。就使用的字节数而言,UTF-8 相当紧凑。当用于东亚实现(例如中文、日文和韩文)时,它实际上只是在大小上处于显着劣势,这些实现使用需要 UTF-8 中的三字节代码单元序列的韩语表意文字或韩文音节。UTF-8 在处理方面的效率也明显低于其他编码形式。二进制排序。UTF-8 字符串的二进制排序与 Unicode 代码点的二进制排序相同。这显然与二进制排序的 UTF-32 字符串的顺序相同。
一般结构
当只处理 BMP 字符(在 U+0000..U+FFFF 范围内)时,所有三种编码形式对于二进制字符串比较或字符串排序给出相同的结果。但是,在处理补充字符时(在 U+10000..U+10FFFF 范围内),UTF-16 二进制顺序与 Unicode 代码点顺序不匹配。当尝试与二进制排序列表进行互操作时,这可能会导致复杂化——例如,在 UTF-16 系统和 UTF-8 或 UTF-32 系统之间。但是,对于根据特定语言或区域设置而不是使用二进制顺序排序的数据,无论编码形式如何,数据都将按相同的顺序排序。
简短的回答:没有。
更长的答案:是的,为了与其他没有得到备忘录的东西兼容。
不那么讽刺的回答:当您更关心索引速度而不是空间使用时,或者作为某种中间格式,或者在对齐问题比缓存问题更重要的机器上,或者......
UTF-8 也可以表示任何 unicode 字符!
如果你的文本主要是英文,你可以通过使用 utf-8 节省大量空间,但索引字符不是 O(1),因为有些字符占用不止一个字节。
如果空间对您的情况不像速度那么重要,utf-32 会更适合您,因为索引是 O(1)
对于非英语文本,UTF-16 可能比 utf-8 更好,因为在 utf-8 中,有些字符占用 3 个字节,而在 utf16 中它们只占用两个字节。
可能有几个很好的理由,但一个是加快索引/搜索,即在数据库等中。
使用 UTF-32,您知道每个字符是 4 个字节。使用 UTF-16,您不知道任何特定字符的长度。
例如,您有一个返回字符串的第 n 个字符的函数:
char getChar(int index, String s );
如果您正在使用具有直接内存访问权限的语言(例如 C)进行编码,那么在 UTF-32 中,此函数可能就像一些指针算术 ( s+(4*index)
) 一样简单,其数量为 O(1)。
但是,如果您使用的是 UTF-16,则必须遍历字符串,边进行解码,这将是 O(n)。
通常,您只需使用底层平台的字符串数据类型/编码,通常是(Windows、Java、Cocoa...)UTF-16,有时是 UTF-8 或 UTF-32。这主要是出于历史原因;三种 Unicode 编码之间几乎没有区别:这三种都定义明确、快速且健壮,并且它们都可以编码每个 Unicode 代码点序列。UTF-32 的独特之处在于它是一种固定宽度编码(意味着每个代码点都由一个代码单元表示)在实践中几乎没有用处:您的内存管理层需要了解代码的数量和宽度单位,用户对抽象字符和字素感兴趣。正如 Unicode 标准所提到的,Unicode 应用程序必须处理组合字符、连字等以及代理对的处理,
如果我要重塑世界,我可能会选择 UTF-32,因为它只是最简单的编码,但就目前而言,差异太小而无法引起实际关注。