何时使用Unicode规范化形式NFC和NFD?

Jes*_*lam 21 string unicode normalization unicode-normalization

Unicode规范化常见问题包括以下内容:

程序应始终将规范等效的Unicode字符串比较为相等... Unicode标准提供了可用于此的明确定义的规范化形式:NFC和NFD.

继续......

选择使用哪个取决于特定的程序或系统.NFC是一般文本的最佳形式,因为它与从传统编码转换的字符串更兼容.... NFD和NFKD对内部处理最有用.

我的问题是:

什么使NFC成为"一般文本"的最佳选择.什么定义"内部处理",为什么最好留给NFD?最后,只要使用相同的规范化形式比较两个字符串,两个形式可以互换,从不关注什么是"最佳"?

Juk*_*ela 10

常见问题解答有点误导,从使用"应该"开始,然后是对"同一件事"的"要求"的不一致使用.Unicode标准本身(在FAQ中引用)更准确.基本上,您不应期望程序将规范等效的字符串视为不同的字符串,但您也不应期望所有程序都将它们视为相同.

实际上,它实际上取决于您的软件需要做什么.在大多数情况下,您根本不需要进行标准化,标准化可能会破坏数据中的基本信息.

例如,U + 0387 GREEK ANO TELEIA(·)被定义为规范等效于U + 00B7 MIDDLE DOT(·).这是一个错误,因为角色非常独特,应该以不同的方式呈现,并在处理过程中区别对待.但改变这一点为时已晚,因为Unicode的这一部分已被刻入石头.因此,如果您将数据转换为NFC或以其他方式丢弃规范等效字符串之间的差异,则可能会出现错误字符.

通过规范化可能会带来风险.例如,字母"ä"可以显示为单个Unicode字符U + 00E4 LATIN SMALL LETTER A WITH DIAERESIS或两个Unicode字符U + 0061 LATIN SMALL LETTER A U + 0308 COMBINING DIAERESIS.它主要是前者,即预组合形式,但如果它是后者并且您的代码测试包含"ä"的数据,仅使用预组合形式,那么它将不会检测后者.但在许多情况下,你不会做这些事情,只是简单地存储数据,连接字符串,打印它们等等.然后存在这两种表示导致稍微不同的渲染的风险.

您的软件是否以某种方式将字符数据传递给其他软件也很重要.由于天真的隐含假设或者有意识地并且以文档化的方式,接收者可能期望其输入被标准化.

  • [技术说明TN1150/HFS Plus卷格式/ Unicode细节](https://developer.apple.com/legacy/library/technotes/tn/tn1150.html#UnicodeSubtleties) (2认同)

Esa*_*ija 5

  1. NFC是您应该使用的一般常识形式,在这里ä只有1个代码点,这很有意义。

  2. NFD适用于某些内部处理-如果您要进行不区分重音符号的搜索或排序,则将字符串包含在NFD中会使其变得更加轻松快捷。另一个用法是制作更强大的子弹头称号。这些只是最明显的用途,我相信还有更多的用途。

  3. 如果两个字符串x和y是规范等效项,则
    toNFC(x)= toNFC(y)
    toNFD(x)= toNFD(y)

    这是你的意思吗?

  • Re 3,我认为情况并非总是如此。例如(来自维基百科)字符串 1 包含“U+212B”(埃符号“Å”),字符串 2 包含“U+0041 U+030A”(拉丁字母“A”和“°”上方的组合环)。在NFD下,它们是等价的,但在NFC下字符串2被转换为“U+00C5”(瑞典字母“Å”),所以两者不等价。在我看来,NFD 是最安全的选择。http://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms (2认同)