检查无效的UTF8

Mar*_*ark 10 c++ utf-8

我将从UTF8格式转换为十六进制的实际值.但是,我需要捕获一些无效的字节序列.有没有一种快速方法可以检查角色是否属于C++中的UTF8?

Jon*_*ler 14

请遵循Unicode标准第3章中的表格.(我使用了本章的Unicode 5.1.0版本(p103);它是Unicode 6.0.0版本的p94上的表3-7,并且是Unicode中的p95 6.3版本 - 它位于Unicode 8.0.0版本的p125上.)

字节0xC0,0xC1和0xF5..0xFF不能出现在有效的UTF-8中.记录有效序列; 所有其他人都无效.

表3-7.良好的UTF-8字节序列

Code Points        First Byte Second Byte Third Byte Fourth Byte
U+0000..U+007F     00..7F
U+0080..U+07FF     C2..DF     80..BF
U+0800..U+0FFF     E0         A0..BF      80..BF
U+1000..U+CFFF     E1..EC     80..BF      80..BF
U+D000..U+D7FF     ED         80..9F      80..BF
U+E000..U+FFFF     EE..EF     80..BF      80..BF
U+10000..U+3FFFF   F0         90..BF      80..BF     80..BF
U+40000..U+FFFFF   F1..F3     80..BF      80..BF     80..BF
U+100000..U+10FFFF F4         80..8F      80..BF     80..BF
Run Code Online (Sandbox Code Playgroud)

注意,对于第一字节的某些值范围,不规则性在第二字节中.需要时,第三个和第四个字节是一致的.请注意,并非所有已标识为有效的范围内的代码点都已分配(并且某些代码点明确为"非字符"),因此仍需要更多验证.

代码点U + D800..U + DBFF用于UTF-16高代理,U + DC00..U + DFFF用于UTF-16低代理; 那些不能出现在有效的UTF-8中(您将编码BMP外部的值 - 基本多语言平面 - 直接以UTF-8编码),这就是该范围被标记为无效的原因.

其他排除范围(初始字节C0或C1,或初始字节E0后跟80..9F,或初始字节F0后跟80..8F)是非最小编码.例如,C0 80将编码U + 0000,但是其由00编码,并且UTF-8定义非最小编码C0 80无效.最大的Unicode代码点是U + 10FFFF; 从F4 90向上开始的UTF-8编码生成超出范围的值.


Ker*_* SB 6

已经很好的答案,我只是为了好玩而在另一个角色上扯皮.

UTF-8使用Prosser和Thompson的一般方案来编码单字节序列中的大数字.这个方案实际上可以代表2 ^ 36个值,但对于Unicode,我们只需要2 ^ 21个.这是它的工作原理.设N是要编码的数字(例如Unicode代码点):

  • 如果N <128,只需一个字节0nnnnnnn.最高位为零.
  • 否则,几个字节.第一个字节的开头数与序列中的字节数一样多,然后是零,然后是数据位; 连续字节开始10后跟六个数据位.例子:
  • 3字节序列:1110xxxx 10xxxxxx 10xxxxxx.
  • 5字节序列:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx.
  • 7字节序列:11111110 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx.

ķ字节序列装配5 ķ + 1位(当ķ > 1),所以可以确定需要多少个字节给定N的解码,读一个字节; 如果其顶部位为零,则按原样存储其值,否则使用第一个字节计算序列中的字节数并处理所有这些字节.

对于今天的Unicode,我们最多只需要k = 4个字节.