为什么`utf8.Valid()` 认为某些有效的 UTF-8 代码无效?

use*_*739 -1 utf-8 go

$ cat main.go

package main

import (
    "fmt"
    "unicode/utf8"
    "io/ioutil"
    "os"
    "log"
)

func main() {
    str, err := ioutil.ReadFile(os.Args[1])
    if err != nil { log.Fatal(err) }
    fmt.Println(utf8.Valid([]byte(str)))
}
$ go run main.go <(echo $'\xed\xa0\xb5')
false
Run Code Online (Sandbox Code Playgroud)

utf8.Valid() 说 '\xed\xa0\xb5' 无效。

  • \xed11101101
  • \xa010100000
  • \xb510110101

但是有二进制格式的三个字节。111xxxxx表示它是一个三个字节的字符。根据维基页面上的表格,以下两个字节应该有效。

https://en.wikipedia.org/wiki/UTF-8

有人知道为什么utf8.Valid()将三字节字符显示为无效的 UTF-8 字符吗?

T0x*_*ode 7

根据维基百科上的代码页布局表,虽然十六进制序列\xed\xa0\xb5遵循 处代码点的编码规则0xd835,但它被认为是无效的,因为它与 UTF-16 中为代理半部分保留的代码点相匹配。查看Unicode的代码点表时,您会看到来自0xD800to的代码点都未0xDFFF分配并标记为“在 UTF-8 中显式无效”。

Unicode 和 ISO/IEC 10646 不会将实际字符分配给 D800–DFFF 范围内的任何代码点——这些代码点仅在用于代理对时才有意义。因此,代理对中的单个代码点不代表字符,除非在代理对中使用,否则无效,并且在 UTF-32 和 UTF-8 中无条件无效(如果应用严格符合标准)。