(begin curved line) (char1) (char2) … (charN) (end curved line)
而不是这样的:(curved line marker prefix) (char1) (curved line marker prefix) (char2) (curved line marker prefix) (char2)
。换句话说,可以渲染的最小单位是多少?
(begin curved line) (char1) (char2) … (charN) (end curved line)
而不是这样的:(curved line marker prefix) (char1) (curved line marker prefix) (char2) (curved line marker prefix) (char2)
。换句话说,可以渲染的最小单位是多少?
Answers:
Unicode包括多种编码某些字符(最著名的是重音字符)的方法。规范化规范将代码点更改为规范编码形式。生成的代码点应与原始代码点相同,除非字体或渲染引擎中有任何错误。
因为结果看起来相同,所以在存储或显示字符串之前对字符串进行规范化归类总是安全的,只要您可以容忍结果与输入不完全相同即可。
规范化归纳有两种形式:NFD和NFC。从一个人可以在这两种形式之间进行转换而不会造成损失的意义上来说,两者是等效的。在NFC下比较两个字符串将始终得到与在NFD下比较两个字符串相同的结果。
NFD的字符已完全扩展。这是计算速度更快的规范化形式,但是会导致更多的代码点(即,使用更多的空间)。
如果只想比较尚未标准化的两个字符串,则这是首选的标准化形式,除非您知道需要兼容性标准化。
运行NFD算法后,NFC会在可能的情况下重组代码点。这会花费更长的时间,但会导致字符串更短。
Unicode还包括许多实际上不属于但在旧式字符集中使用的字符。Unicode添加了这些功能,以允许将这些字符集中的文本作为Unicode处理,然后无损地转换回去。
兼容性规范化将它们转换为相应的“真实”字符序列,并执行规范规范化。兼容性归一化的结果可能与原始结果不一样。
包含格式信息的字符将被不包含格式信息的字符替换。例如,字符⁹
被转换为9
。其他不涉及格式差异。例如,罗马数字字符Ⅸ
被转换为常规字母IX
。
显然,一旦执行了此转换,就不再可能无损地转换回原始字符集。
Unicode联合会建议将兼容性规范化视为一种ToUpperCase
转换。这在某些情况下可能有用,但您不应该随便使用它。
一个很好的用例是搜索引擎,因为您可能希望搜索9
匹配⁹
。
您可能不应该做的一件事是显示对用户应用兼容性标准化的结果。
兼容性规范化形式有两种形式:NFKD和NFKC。它们与NFD和C之间的关系相同。
NFKC中的任何字符串本质上也是NFC中的,对于NFKD和NFD也是相同的。因此NFKD(x)=NFD(NFKC(x))
,和NFKC(x)=NFC(NFKD(x))
等。
如有疑问,请进行规范化归一化处理。根据适用的空间/速度权衡,或根据互操作对象的要求选择NFC或NFD。
NFC(x)=Recompose(NFD(x))
。
某些字符(例如带有重音符号(例如)的字母é
)可以两种方式表示-单个代码点U+00E9
或纯字母后跟组合的重音符号U+0065 U+0301
。普通归一化将选择其中之一来始终表示它(NFC的单个代码点,NFD的组合形式)。
对于可以由多个基本字符序列和组合标记表示的字符(例如,“ s,在下面的点,在上面的点”与将点放在上面然后在点下或使用已经具有一个点的基本字符),NFD将还要选择其中一个(发生的情况如下)
兼容性分解包括许多“本不应该”为字符的字符,但是因为它们是在旧式编码中使用的。普通规范化不会统一这些规范(以保持往返完整性-这对于合并表单来说不是问题,因为没有传统编码(少数越南编码除外)都使用这两种编码),但是兼容性规范化却可以。就像出现在某些东亚编码(或半角/全角片假名和字母)中的“ kg”公斤符号,或MacRoman中的“ fi”连字一样。
有关更多详细信息,请参见http://unicode.org/reports/tr15/。
普通格式(Unicode,而不是数据库)主要(唯一地?)处理带有变音标记的字符。Unicode提供了一些带有“内置”变音标记的字符,例如U + 00C0,“带有Grave的拉丁大写字母A”。可以从“拉丁大写字母A”(U + 0041)和“合并重音符号”(U + 0300)创建相同的字符,这意味着即使两个序列产生相同的结果字符,也要逐字节比较将显示它们完全不同。
规范化是对此的一种尝试。规范化确保(或至少尝试)以相同的方式编码所有字符-要么在需要时全部使用单独的组合变音标记,要么在可能的情况下全部使用单个代码点。从比较的角度来看,选择的内容并不重要,几乎所有标准化字符串都可以与另一个标准化字符串进行正确比较。
在这种情况下,“兼容性”是指与假定一个代码点等于一个字符的代码的兼容性。如果您有这样的代码,则可能要使用兼容性标准格式。尽管我从未见过它直接说明过,但正常形式的名称暗示着Unicode联盟认为最好使用单独的组合变音标记。这需要更多的智能来计算字符串中的实际字符(以及智能地断开字符串之类的事情),但是用途更多。
如果您充分利用ICU,则很有可能要使用规范的标准格式。如果您尝试自己编写代码(例如,假设一个代码点等于一个字符),那么您可能希望使用兼容性规范形式,以尽可能多地实现这一点。
"o\x{332}\x{303}\x{304}"
,而NFC是"\x{22D}\x{332}"
。对于第二个NFD是"o\x{332}\x{304}\x{303}"
和NFC是"\x{14D}\x{332}\x{303}"
。但是,存在许多非规范的可能性,这些可能性在规范上等同于这些可能性。归一化允许规范等效的字素的二进制比较。
这实际上很简单。UTF-8实际上具有相同“字符”的几种不同表示形式。(我在引号中使用字符,因为它们在字节方向上是不同的,但实际上它们是相同的)。链接文档中提供了一个示例。
字符“Ç”可以表示为字节序列0xc387。但是它也可以由C
(0x43)表示,后跟字节序列0xcca7。因此,可以说0xc387和0x43cca7是同一字符。起作用的原因是0xcca7是一个组合标记。也就是说,它需要一个字符(在C
此处为a )并对其进行修改。
现在,至于规范对等与兼容性对等之间的差异,我们通常需要看一下字符。
有两种类型的字符,一种通过值传达含义,另一种则采用另一个字符并对其进行更改。9是有意义的字符。上标⁹具有该含义,并通过表示进行更改。因此,规范地它们具有不同的含义,但是它们仍然代表基本字符。
规范对等是字节序列呈现具有相同含义的相同字符的地方。兼容性等效是指字节序列呈现具有相同基本含义的不同字符(即使可以更改)。9和⁹是兼容性等效的,因为它们均表示“ 9”,但由于它们的表示形式不同,因此在规范上不是等效的。
规范对等还是兼容性对等与您更相关,取决于您的应用程序。考虑字符串比较的ASCII方式大致映射为规范对等,但是Unicode代表许多语言。我认为以Unicode对所有语言进行编码而使您像对待西欧ASCII一样对待它们是不安全的。
图1和2提供了两种等效形式的良好示例。在兼容性等效下,子脚本和上脚本形式的相同数字看起来将相等。但是我不确定能解决与草书阿拉伯形式或旋转字符相同的问题。
Unicode文本处理的硬道理是,您必须深入考虑应用程序的文本处理要求,然后使用可用的工具尽可能地解决它们。那并不能直接解决您的问题,但是更详细的答案将需要您要支持的每种语言的语言专家。
比较字符串的问题:对于大多数应用程序而言,两个内容相同的字符串可能包含不同的字符序列。
请参阅Unicode的规范对等:如果比较算法简单(或必须很快),则不执行Unicode对等。发生此问题,例如在XML规范比较中,请参阅 http://www.w3.org/TR/xml-c14n
为避免此问题...使用什么标准?“扩展UTF8”还是“紧凑UTF8”?
使用“ç”还是“ c +◌̧”?
W3C和其他(例如文件名)建议使用“按规范构成”(请记住C是“最紧凑”的较短字符串)...因此,
为了实现互操作性以及“通过配置进行约定”,建议使用NFC来“规范化”外部字符串。例如,要存储规范的XML,请将其存储在“ FORM_C”中。Web工作组上的 W3C CSV也推荐了NFC(第7.2节)。
PS:de“ FORM_C”是大多数库中的默认格式。例如 在PHP的normalizer.isnormalized()中。
疗法术语“ compostion表”( FORM_C
)用于这两个,说“这样的字符串是在C-规范表”(一NFC转换的结果),并说一个变换算法用于...查看HTTP: //www.macchiato.com/unicode/nfc-faq
(...)以下每个序列(前两个是单字符序列)表示相同字符:
- U + 00C5(Å)带环的拉丁文大写字母A
- U + 212B(Å)天使标志
- U + 0041(A)拉丁文大写字母A + U + 030A(̊)组合环
这些序列称为规范等效。第一这些形式被称为NFC -用于规范化表C,其中C是compostion。(...)将字符串S转换为NFC形式的函数可以缩写为
toNFC(S)
,而将测试S是否在NFC中的函数缩写为isNFC(S)
。
注意:要测试小字符串(纯UTF-8或XML实体引用)的规范化,可以使用此测试/规范化在线转换器。