在 C++ 中编码独立的输入流

Encoding independent input stream in C++

我有一个读取文本文件的 C++ 程序。目前我正在使用 C 的 fopen() 来读取然后 fgetc() 来读取下一个字符。 我 typedef 有一个 "file character",它实际上是一个 int(显然我可以毫无问题地将其更改为 long)。

现在程序可以读取UTF-7和UTF-8文本文件,但是如果我使用UTF-16或UTF-32文本文件呢?有没有办法推断文件编码然后正确读取文件? 即使传递给 C++ 的 istream 也不是问题。

对于任意字节流,没有办法可靠地计算出来。您可以用相同的方式打开二进制可执行文件,该文件未使用任何上述编码进行编码。

你能做的就是尝试猜测。将文件视为二进制文件并读取前 10k 字节或类似内容,然后将字节值的分布与您构建的一些规范模型进行比较,看看哪个最接近,然后使用那个。

要构建这样的模型,您可以使用一些文本(您已经拥有的内容或从维基百科复制的一些文章)对它们进行各种编码和 运行 相同的算法来构建分布。平均结果并将其用作比较的规范模型。当您倾向于使用相同类型的文本时效果最佳(即,如果您使用纯英文文本构建模型,则可能难以使用非 ascii 字符对文档进行分类)。

如果您的文件有一个 byte order mark,它会有很大帮助。

虽然您不能绝对推断,但在实践中,您可能会根据编码列表尝试失败。

  • UTF-16 很可能很早就有一个'\0'(无论是在偶数还是奇数位置由字节顺序决定,字节顺序可能是小的,大的,或者在某些体系结构上,中等);
  • UTF-32 可能会有其中三个;而
  • UTF-8 字符串不应该有这个字符。

此外,允许(但不是必需)utf 文件存储字节顺序标记:https://en.wikipedia.org/wiki/Byte_order_mark。如果你有它,那你很幸运,因为这在编码中是不同的。