如果你问如何构造一个非 UTF-8 字符,那应该很容易从this definition from Wikipedia:
对于代码点 U+0000 到 U+007F,每个代码点都是一个字节长,如下所示:
0xxxxxxx // a
对于代码点 U+0080 到 U+07FF,每个代码点长两个字节,如下所示:
110xxxxx 10xxxxxx // b
等等。
因此,要构造一个非法 UTF-8 字符,长度为一个字节,最高位必须为 1(与模式 a 不同),第二高位必须为 0(与模式 b 不同):
10xxxxxx
或
111xxxxx
这也不同于两种模式。
同样的逻辑,你可以构造超过两个字节长的非法代码单元序列。
您没有标记语言,但我必须对其进行测试,所以我使用了 Java:
for (int i=0;i<255;i++) {
System.out.println(
i + " " +
(byte)i + " " +
Integer.toHexString(i) + " " +
String.format("%8s", Integer.toBinaryString(i)).replace(' ', '0') + " " +
new String(new byte[]{(byte)i},"UTF-8")
);
}
0 到 31 是不可打印字符,然后 32 是空格,后面是可打印字符:
...
31 31 1f 00011111
32 32 20 00100000
33 33 21 00100001 !
...
126 126 7e 01111110 ~
127 127 7f 01111111
128 -128 80 10000000 �
delete 是 0x7f 并且在它之后,从 128 到 254 不打印有效字符。从UTF-8 chartable也可以看到:
代码点U+007F用一个字节0x7F(位01111111)表示,而代码点U+0080用两个字节0xC2 0x80(位11000010 10000000)表示。
如果您不熟悉 UTF-8,我强烈建议您阅读这篇优秀的文章:
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)