Xeo*_*oss 125 php c unicode unicode-normalization
Kev*_*art 173
Unicode包括多种编码某些字符的方法,最明显的是重音字符.规范化规范化将代码点更改为规范编码形式.生成的代码点应该与原始代码点相同,除非字体或渲染引擎中存在任何错误.
因为结果看起来相同,所以在存储或显示结果之前对字符串应用规范标准化总是安全的,只要您能够容忍结果与输入的位不相同.
规范归一化有两种形式:NFD和NFC.这两者在某种意义上是等价的,即可以在这两种形式之间进行转换而不会丢失.在NFC下比较两个字符串将始终提供与在NFD下比较它们相同的结果.
NFD的角色已经完全展开.这是要计算的更快的规范化形式,但结果是更多的代码点(即使用更多的空间).
如果您只想比较两个尚未规范化的字符串,除非您知道需要兼容性规范化,否则这是首选的规范化形式.
在运行NFD算法后,NFC会尽可能重新组合代码点.这需要更长的时间,但会导致更短的字符串.
Unicode还包括许多真正不属于但在旧版字符集中使用的字符.Unicode添加了这些以允许将这些字符集中的文本作为Unicode处理,然后转换回来而不会丢失.
兼容性规范化将这些转换为相应的"真实"字符序列,并执行规范规范化.兼容性标准化的结果可能看起来与原件不同.
包含格式信息的字符将替换为不包含格式信息的字符.例如,角色?转换为9.其他人不涉及格式差异.例如,罗马数字字符?被转换为常规字母IX.
显然,一旦执行了这种转换,就不再可能无损地转换回原始字符集.
Unicode Consortium建议考虑兼容性规范化,如ToUpperCase变换.在某些情况下,这可能是有用的,但你不应该只是毫不犹豫地应用它.
一个很好的用例是搜索引擎,因为您可能希望搜索9匹配?.
您可能不应该做的一件事是显示将兼容性规范化应用于用户的结果.
兼容性规范化形式有两种形式NFKD和NFKC.它们与NFD和C之间具有相同的关系.
NFKC中的任何字符串本身也在NFC中,对于NFKD和NFD也是如此.因此NFKD(x)=NFD(NFKC(x)),与NFKC(x)=NFC(NFKD(x))等
如果有疑问,请遵循规范规范化.根据适用的空间/速度权衡,或根据您与之互操作的要求,选择NFC或NFD.
Ran*_*832 39
某些字符,例如带有重音的字母(例如é),可以用两种方式表示 - 单个代码点U+00E9或普通字母后跟组合重音符号U+0065 U+0301.普通规范化将选择其中一个来表示它(NFC的单个代码点,NFD的组合形式).
对于可以由多个基本字符序列和组合标记表示的字符(例如,"s,点下方,上方点"与"将点放在上方,然后点在下方"或使用已经具有其中一个点的基本字符),NFD将也选择其中之一(下面首先,因为它发生)
兼容性分解包括许多"不应该"确实是字符的字符,但是因为它们在遗留编码中使用.普通规范化不会统一这些(为了保持往返完整性 - 这不是组合形式的问题,因为没有遗留编码[除了少数越南编码]两者都使用),但兼容性规范化将会.想象一下东亚编码(或半宽/全宽片假名和字母表)或MacRoman中的"fi"连字中出现的"kg"千克符号.
有关详细信息,请参见http://unicode.org/reports/tr15/.
Jer*_*fin 13
正常形式(Unicode,而不是数据库)主要(仅限于?)处理具有变音符号的字符.Unicode提供了一些带有"内置"变音符号的字符,例如U + 00C0,"Latin Capital A with Grave".可以使用"Combined Grave Accent"(U + 0300)从"Latin Capital A"(U + 0041)创建相同的字符.这意味着即使两个序列产生相同的结果字符,也是逐字节的比较将显示它们完全不同.
规范化是试图解决这个问题.规范化确保(或至少尝试)所有字符以相同的方式编码 - 或者在需要时使用单独的组合变音符号,或者尽可能使用单个代码点.从比较的角度来看,你选择的很多并不重要 - 几乎任何规范化的字符串都会与另一个规范化的字符串正确比较.
在这种情况下,"兼容性"意味着与假定一个代码点等于一个字符的代码的兼容性.如果你有这样的代码,你可能想要使用兼容性的普通形式.虽然我从未见过直接说明,但正常形式的名称暗示Unicode联盟认为最好使用单独的组合变音符号.这需要更多的智能来计算字符串中的实际字符(以及智能地打破字符串等),但是更加通用.
如果您正在充分利用ICU,那么您可能希望使用规范的正常形式.如果您正在尝试自己编写代码(例如)假设代码点等于某个字符,那么您可能需要兼容性正常形式,以尽可能频繁地生成该代码.
如果两个unicode字符串在规范上等效,则字符串实际上是相同的,只使用不同的unicode序列.例如,Ä可以使用字符Ä或A和combination的组合来表示.
如果字符串仅是兼容性等同,则字符串不一定相同,但在某些上下文中它们可能相同.例如,ff可以被认为与ff相同.
所以,如果你要比较字符串,你应该使用规范等价,因为兼容性等价不是真正的等价.
但是如果你想对一组字符串进行排序,那么使用兼容性等价可能是有意义的,因为几乎相同.
这实际上相当简单。UTF-8 实际上对同一个“字符”有几种不同的表示。(我在引号中使用字符,因为它们在字节方面是不同的,但实际上它们是相同的)。链接文档中给出了一个示例。
字符“Ç”可以表示为字节序列 0xc387。但也可以用一个C(0x43) 后跟字节序列 0xcca7 来表示。所以你可以说 0xc387 和 0x43cca7 是同一个字符。有效的原因是 0xcca7 是一个组合标记;也就是说,它接受它之前的字符(C这里是 a ),并修改它。
现在,至于规范等价与兼容性等价之间的区别,我们需要了解一般的字符。
有两种类型的字符,一种是通过value传达意义的字符,另一种是采用另一个字符并改变它的字符。9是一个有意义的字符。一个超级脚本?接受这个意义并通过呈现来改变它。因此,规范地它们具有不同的含义,但它们仍然代表基本字符。
规范等价是字节序列呈现具有相同含义的相同字符。兼容性等效是当字节序列呈现具有相同基本含义的不同字符时(即使它可能被更改)。9 和 ? 兼容性等效,因为它们都表示“9”,但不是规范等效的,因为它们没有相同的表示。