使用位移来猜测 UTF-8 编码

nin*_*and 2 c utf-8 bit-shift

我正在编写一个像 file(1) 这样的程序,它可以猜测文本文件是否包含 ascii 字符、ISO-8859-1 字符或 UTF-8。我已经将其编程为猜测 ascii 和 ISO,只剩下 UTF-8。我的问题是我应该使用位移位,虽然我知道位移位的基础知识,但我无法弄清楚如何使用它来猜测 UTF-8 字符。我当然不是在寻求解决方案,但如果有人能将我推向正确的方向,我会很高兴!

我是用C写的。

Dan*_*ein 6

对此的任何解决方案都将是基于启发式的。但一般来说,UTF-8 有以下字节序列(可在 参考资料中找到man utf8):

0x00000000 - 0x0000007F:
    0xxxxxxx
0x00000080 - 0x000007FF:
    110xxxxx 10xxxxxx
0x00000800 - 0x0000FFFF:
    1110xxxx 10xxxxxx 10xxxxxx
0x00010000 - 0x001FFFFF:
    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Run Code Online (Sandbox Code Playgroud)

因此,您的启发式方法可以向前查看几个字节,并查看字节是否遵循四种模式之一(UTF-8 理论上支持字节序列拉伸到六个字符,但实际上只使用四个):

  1. 0*(您必须小心地将其与常规 ASCII 文件区分开)
  2. 110*,10*
  3. 1110*, 10*,10*
  4. 11110*, 10*, 10*,10*

检查这些很容易:

要检查 a 是否unsigned char a适合这些模式之一,请运行:

  1. 对于10*- 最常用的模式 - 使用(a >> 6) == 0x2
  2. 用来。0*(a >> 7) == 0x0
  3. 用来。110*(a >> 5) == 0x6
  4. 用来。1110*(a >> 4) == 0xe
  5. 用来。11110*(a >> 3) == 0x1e

我们所做的就是将这些位向右移动并检查它们是否等于 UTF-8 字节序列中的位。

  • 尽管 UTF8 在技术上可以支持长度超过 4 个字节的字节序列,但事实并非如此。U+10FFFF 以上的代码点无效。 (2认同)
  • @TedLyngmo 糟糕,已修复。 (2认同)