给定一个UTF-8字符串,在搜索ASCII字符时可以将其视为字节字符串吗?

时间:2018-06-22 06:53:54

标签: unicode

由于许多现代语言中的字符串现在都是Unicode字符序列,因此它可以跨越多个字节。但是,如果我只关心某些ASCII字符,将字符串视为字节序列是否安全(假设给定的字符串是有效的Unicode字符序列)?

2 个答案:

答案 0 :(得分:1)

删除unicode字符的概念,而不是谈论 unicode编码点(例如U + 0065:“拉丁文小写字母E”)和不同的编码,这很有帮助。 em>(ASCII,UTF-8,UTF-16等)。您正在询问UTF-8编码的属性。对于UTF-8:U + 0080以下的代码点具有与ASCII相同的编码。 wikipedia page有一张漂亮的桌子

Number      Bits for     First       Last        Byte 1    Byte 2
of bytes    code point   code point  code point   
1           7            U+0000      U+007F      0xxxxxxx
2           11           U+0080      U+07FF      110xxxxx  10xxxxxx
...

在我看来,谈论语言中的字符串太宽泛了,因为即使您使用某种指定的编码来存储字符串值,您仍然可以使用其他编码来接收输入。 (想想一个Java程序(内部使用UTF-16表示。您仍然可以将字符串序列化为UTF-8或获取以ASCII编码的用户输入。)

答案 1 :(得分:1)

来自Wikipedia

[...]将非ASCII代码点编码为UTF-8 [...]时,不会出现ASCII字节

此外,7位字节(最高有效位为0的字节)永远不会出现在多字节序列中,并且没有有效的多字节序列会解码为ASCII码点。 [...]因此,UTF-8流中的7位字节仅代表流中的所有ASCII字符。因此,通过将UTF-8字节流视为一个单字节字符序列,而无需对多字节序列进行解码,许多[程序]将继续按预期工作。

来自utf8everywhere.org

通过这种编码的设计,UTF-8保证ASCII字符值或子字符串永远不会与多字节编码字符的一部分匹配。

维基百科的这张表很好地展现了这一点:

Number of bytes   Byte 1     Byte 2     Byte 3     Byte 4
1                 0xxxxxxx             
2                 110xxxxx   10xxxxxx        
3                 1110xxxx   10xxxxxx   10xxxxxx    
4                 11110xxx   10xxxxxx   10xxxxxx   10xxxxxx

被视为8位字节的所有ASCII字符的最高有效位都设置为0。但是在多字节编码字符中,所有字节的MSB均设置为1。


请注意,UTF8是Unicode的一种编码。他们是不一样的!我的答案是关于UTF8编码的字符串(幸运的是最突出的编码)。

要注意的另一件事是Unicode规范化,它将字符和“种类”包含ASCII字符的其他字符组合在一起。以Umlautä为例:

ä      0xC3A4    LATIN SMALL LETTER A WITH DIAERESIS
ä      0x61CC88  LATIN SMALL LETTER A  +  COMBINING DIAERESIS

如果搜索ASCII字符“ a”,尽管在逻辑上包含相同的“用户可感知字符”,但您会在第二行找到它,而在第一行找不到。您可以通过预先规范化字符串来至少部分地解决此问题。