【问题标题】:How to test whether a binary string is valid UTF8?如何测试二进制字符串是否是有效的 UTF8?
【发布时间】:2020-06-13 04:24:39
【问题描述】:

https://github.com/google/codesearch/blob/master/index/write.go#L581

我看上面是为了测试两个字节是否可以出现在一个有效的 UTF8 字符串中。但我不明白它是如何工作的。谁能帮我理解为什么这个功能有效?谢谢。

【问题讨论】:

    标签: go utf-8


    【解决方案1】:

    有关编码的说明,请参阅wikipedia。编码为:

    num
    bytes 1st byte  2nd byte  3rd byte  4 byte
    1     0xxxxxxx          
    2     110xxxxx  10xxxxxx        
    3     1110xxxx  10xxxxxx  10xxxxxx  
    4     11110xxx  10xxxxxx  10xxxxxx 10xxxxxx
    

    为了帮助使代码更容易与维基百科文章进行比较,这里的代码将 < n 重写为 <= n-1 并将整数文字重写为二进制整数文字。

    func validUTF8(c1, c2 uint32) bool {
        switch {
        case c1 <= 0b01111111:
            // 1-byte, must be followed by 1-byte or first of multi-byte
            return c2 <= 0b01111111 || 0b11000000 <= c2 && c2 <= 0b11110111
        case c1 <= 0b10111111:
            // continuation byte, can be followed by nearly anything
            return c2 <= 0b11110111
        case c1 <= 0b11110111:
            // first of multi-byte, must be followed by continuation byte
            return 0b10000000 <= c2 && c2 <= 0b10111111
        }
        return false
    }
    

    第一种情况检查 1 字节编码 (0xxxxxxx) 之后的字节。

    第二种情况检查后续字节(10xxxxxx)之后的字节。

    第三种情况检查多字节编码(110xxxx、1110xxxx、11110xxx)开始之后的字节。

    该函数报告两个字节是否可以采用有效的 UTF-8 编码。有效字节对序列不一定是有效的 UTF-8 编码。

    【讨论】:

      【解决方案2】:

      使用标准库的unicode/utf8 模块可能比使用该函数更适合您的任务。查看utf8.Valid 文档。

      【讨论】:

      • 可能不会,因为整个字符串可能不在内存中。该代码将文本文件中的字节逐块读取到固定大小的缓冲区中,某些 UFT8 字符可能仅部分位于缓冲区中。所以必须每两个字节检查一次。
      • 您仍然可以使用utf8.Valid,每两个字节调用一次。更好的解决方案(性能方面)可能正在处理您的字符串块(考虑边缘情况)。无论如何考虑利用utf8.Valid或其source code
      • 您能解释一下这段代码是如何工作的吗?如果我在字节数组中有一个有效的UTF8字符串,并且我在中间截断字节数组并保留截断之前的部分,那么根据Valid()函数保留的部分是否仍然有效?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      • 2017-05-23
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多