由于许多现代语言中的字符串现在都是Unicode字符序列,因此它可以跨越多个字节。但是,如果我只关心某些ASCII字符,将字符串视为字节序列是否安全(假设给定的字符串是有效的Unicode字符序列)?
答案 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字节流视为一个单字节字符序列,而无需对多字节序列进行解码,许多[程序]将继续按预期工作。
通过这种编码的设计,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”,尽管在逻辑上包含相同的“用户可感知字符”,但您会在第二行找到它,而在第一行找不到。您可以通过预先规范化字符串来至少部分地解决此问题。