检测多字节字符序列?

Detecting multibyte character sequences?

提问人:kerkeslager 提问时间:5/7/2023 最后编辑:skomisakerkeslager 更新时间:5/10/2023 访问量:101

问:

我正在编写一个解析 UTF-8 字符串的解析器。ASCII 范围之外的字符只能出现在字符串文本中,字符串文本以 或 开头和结尾。该语言的其余部分可能只包含 ASCII 字符,因此如果我发现 ASCII 范围之外的字节,我可以简单地返回错误。'"

我似乎无法弄清楚的问题是,当我在字符串文字中遇到非 ASCII 字符时,如何检测该字符要跳过多少字节?我担心的是,如果一个多字节字符包含一个或作为其中一个字节,我的解析器会提前结束字符串文字。'"

也许更短的方法是,如果我遇到 - 范围内的字节,我如何检测 UTF-8 编码字符串中该字符中有多少个字节?0x800xFF

我正在用 C 编写这个解析器,但我怀疑这无关紧要。

C Unicode UTF-8

评论

0赞 user17732522 5/7/2023
为什么要跳过字节?你需要真正解码它们,不是吗?您还需要验证序列是否有效。假设假定的 UTF-8 编码的不受信任字符串实际上是有效的,UTF-8 是漏洞的常见原因。
1赞 user17732522 5/7/2023
这回答了你的问题吗?如何正确跳过 unicode (UTF-8) 字符?
0赞 skomisa 5/8/2023
我知道您的问题独立于任何特定的编程语言,但由于您使用的是 C,因此我添加了一个标签来增加您问题的受众。随意删除它。[c]
1赞 Codo 5/8/2023
维基百科中的第一个表格显示它:en.wikipedia.org/wiki/UTF-8#Encoding

答:

6赞 Rob Napier 5/8/2023 #1

我担心的是,如果多字节字符包含“或”作为字节之一,我的解析器会提前结束字符串文字。

啊,这是你的误会。UTF-8 的精彩之处在于这不会发生。在 UTF-8 中,字节 0x27 只能表示撇点。它永远不能是多字节序列的一部分。这是因为延续字节以设置为 1 的高位开头。

UTF-8 的一个主要设计目标是,在解析 UTF-8 流时,现有和朴素的 ASCII 实现将以相同的方式工作,即使该流包含非 ASCII 字节也是如此。您可以安全地解析并继续累积字节,直到您到达(并用于转义内部),而不必担心 UTF-8 是否涉及多字节字符。ASCII 解析器无需理解 UTF-8 或执行任何 UTF-8 解码即可正常工作。""\"

除此之外,如果你决定你真的想知道问题的答案,第一个字节的前导 1 位数会告诉你长度,除了零个 1 是“1 字节”,一个 1 是“延续”。

0x00 - 0x7F -> 1 byte
0x80 - 0xBF -> (continuation)
0xC0 - 0xDF -> 2 bytes
0xE0 - 0xEF -> 3 bytes
0xF0 - 0xF7 -> 4 bytes

您也可以继续扫描,直到找到 0x00-0x7F 范围内的东西。