我们写了一个C++
应用程序,需要知道这个:
UTF8
文本是否编码从字节到字符的内射映射,这意味着每个字符(字母...)只以一种方式编码?所以,例如字母'Ž'不能编码为3231和32119。
答案 0 :(得分:13)
这在很大程度上取决于你认为的“信件”。
UTF8基本上只是Unicode的一小部分。
基本上至少有三个级别:字节,代码点和Grapheme集群。 根据特定编码,如UTF8,UTF16或UTF32,代码点可以编码为一个或多个字节。此编码是唯一的(因为所有替代方法都被声明为无效)。但是,代码点并不总是字形,因为存在所谓的组合字符。这样的组合字符遵循基本字符,并且如其名称所示,与基本字符组合。例如,有一个组合字符U + 0308 COMBINING DIAERESIS,它将一个分音符(¨)置于前一个字母之上。所以如果它遵循例如a(U + 0061 LATIN SMALL LETTER A),结果是ä。然而,字母ä(U + 00E4 LATIN SMALL LETTER A WITH DIAERESIS)也有一个代码点,所以这意味着代码序列U + 0061 U + 0308和U + 00E4描述了相同的字母。
因此,每个代码点都有一个有效的UTF 8编码(例如U + 0061是“\ 141”,U + 0308是“\ 314 \ 210”而U + 00e4是“\ 303 \ 244”,但是字母ä由代码点序列U + 0061 U + 0308编码,即在UTF8中字节序列“\ 141 \ 314 \ 210”和单个代码点U + 00E4,即字节序列“\ 303 \ 244”
更糟糕的是,由于Unicode制造商决定组合字母跟随基本字母而不是在它之前,你不知道你的字形是否完整,直到你看到下一个代码点(如果它不是组合代码点,则表示您的信件已完成)。
答案 1 :(得分:6)
有效 UTF-8确实对每个字符进行唯一编码。但是,所谓的超长序列符合一般编码方案,但定义无效,因为只有最短的序列可用于编码字符。
例如,UTF-8的衍生物称为 modified UTF-8,它将NUL编码为超长序列0xC0 0x80
而不是0x00
来获取编码与以null结尾的字符串兼容。
如果您要询问字形集群(即用户感知的字符)而不是字符,那么即使有效的UTF-8也不明确。但是,Unicode定义了几个不同的normalization forms,如果你将自己局限于规范化的字符串,那么UTF-8确实是单射的。
有些偏离主题:以下是我想出的一些ASCII艺术,以帮助可视化字符的不同概念。垂直分隔的是 human , abstract 和 machine 级别。随意提出更好的名字......
[user-perceived characters]<-+
^ |
| |
v |
[characters] <-> [grapheme clusters] |
^ ^ |
| | |
v v |
[bytes] <-> [codepoints] [glyphs]<----------+
回到主题:此图表还显示了在使用字节比较抽象字符串时可能出现问题的位置。特别是(假设UTF-8),程序员需要确保
答案 2 :(得分:3)
首先你需要一些术语:
a
+ ́
用于字母á
。每个代码点(例如:U + 1F4A9)获得UTF-8中字节的唯一表示形式(例如:0xF0 0x9F 0x92 0xA9)。
有些字母可以用几种不同的方式表示为代码点(即:作为不同的字形簇)。例如:á
可以表示为单个代码点á
(LATIN SMALL LETTER A WITH ACUTE),或者它可以表示为a
(LATIN SMALL LETTER A)的代码点+ ́
的代码点(COMBINING ACUTE ACCENT)。 Unicode有几种规范的规范化形式来处理这种情况(例如:NFC或规范规范化形式C是一种松散的规范化形式,具有较少的代码点,而NFD被完全分解)。
然后,还有连字(例如:fi
)和一些其他与演示相关的字母变体(例如:上标,不间断空格,在单词的不同位置具有不同形状的字母, ...)。其中一些是Unicode格式,允许无损往返转换为遗留字符集。 Unicode具有兼容性规范化形式(NFKC和NFKD)来处理这个问题。
答案 3 :(得分:2)
是。 UTF-8只是编码Unicode字符的标准方法。这样做是为了只有一种方法来编码每个Unicode字符。
有点偏离主题:知道一些角色在外观上(与人类相似)可能是有用的,但它们仍然不同 - 例如西里尔文中有一个与'/'非常相似的符号。
答案 4 :(得分:0)
是的,有点儿。如果使用得当,每个unicode代码点只应以UTF-8中的一种方式编码,但这部分是因为要求只对任何字符使用最短的适用UTF-8字节序列。
然而,用于对字符进行编码的方法如果不满足此要求,则可以对多个字符进行多种编码 - 虽然不合适,但在某些情况下可以完成此操作。
例如,“Z”可以编码为0x5a
或{0xa1, 0x9a}
(以及其他),但唯一的0x5a
被认为是正确的,因为它是最短的序列。