【问题标题】:Encoding independent input stream in C++ [duplicate]在 C++ 中编码独立的输入流 [重复]
【发布时间】:2016-10-17 01:37:01
【问题描述】:

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

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

【问题讨论】:

  • 祈祷文件有一个Byte Order Mark 你可以阅读然后相应地设置流的语言环境。如果没有,请开始猜测。
  • 正如这个类似问题的答案中所述,以二进制模式读取文件将绕过因与 ASCII 不兼容而造成的任何限制。

标签: c++ encoding utf-8 utf-32


【解决方案1】:

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

  • UTF-16 很可能很早就有一个“\0”(无论是在偶数位置还是奇数位置由字节序决定,字节序可能是小、大或在某些架构上为中);
  • UTF-32 可能包含其中三个;而
  • UTF-8 字符串不应包含此字符。

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

【讨论】:

  • 不适用于非英文文本。如果您需要大量的高阶 unicode 字符,您将不会那么清楚地看到这些模式。
  • 我的问题其实是因为我要读日本表意文字之类的文字,所以没那么容易>
【解决方案2】:

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

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

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

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

【讨论】:

  • OP 询问 UTF-x 编码(到目前为止 :))。 '\0' 字节,对于 x >= 16(最初是 ASCII 字符),实际上 100% 的时间都存在,这使我们能够区分这些 - OTOH 你的回答对于许多不同编码的通用情况非常有趣。
  • @lorro 你假设是英文文本。如果文字大多是☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏和─━│┃┄┆┆┇┈┉┊┋┌┍┎┏'那么你不会看那么多0' 字节,它可能会引发检测。如果您的训练集只有英文文本,它也不适用于我的建议,但如果训练集包含这样的文档,它就有可能工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多