【问题标题】:How Can I Best Guess the Encoding when the BOM (Byte Order Mark) is Missing?当 BOM(字节顺序标记)丢失时,如何最好地猜测编码?
【发布时间】:2010-09-27 05:58:41
【问题描述】:

我的程序必须读取使用各种编码的文件。它们可能是 ANSI、UTF-8 或 UTF-16(大端或小端)。

当BOM(字节顺序标记)在那里时,我没有问题。我知道文件是 UTF-8 还是 UTF-16 BE 或 LE。

我想在没有 BOM 时假设文件是​​ ANSI。但我发现我正在处理的文件经常缺少它们的 BOM。因此,没有 BOM 可能意味着文件是 ANSI、UTF-8、UTF-16 BE 或 LE。

当文件没有 BOM 时,扫描某些文件并最准确地猜测编码类型的最佳方法是什么?如果文件是 ANSI,我希望接近 100% 的时间,如果文件是 UTF 格式,我希望接近 100%。

我正在寻找一种通用的算法方法来确定这一点。但我实际上使用的是 Delphi 2009,它知道 Unicode 并且有一个 TEncoding 类,所以特定的东西会是一个奖励。


答案:

ShreevatsaR 的回答让我在 Google 上搜索“通用编码检测器 delphi”,这让我感到惊讶的是,这篇文章在只存活了大约 45 分钟后就被列为第一名!那是快速的googlebotting! Stackoverflow 如此迅速地获得第一名也令人惊讶。

Google 中的第二个条目是 Fred Eaker 在Character encoding detection 上的博客条目,其中列出了各种语言的算法。

我在该页面上发现了 Delphi 的提及,它直接将我带到了 the Free OpenSource ChsDet Charset Detector at SourceForge,它是用 Delphi 编写的,基于 Mozilla 的 i18n 组件。

太棒了!感谢所有回答的人(全部 +1),感谢 ShreevatsaR,再次感谢 Stackoverflow,帮助我在不到一个小时内找到答案!

【问题讨论】:

  • 感谢编辑! ChsDet 似乎在工作!

标签: algorithm delphi encoding delphi-2009 byte-order-mark


【解决方案1】:

也许您可以使用Chardet: Universal Encoding Detector 编写一个 Python 脚本。它是 Firefox 使用的字符编码检测的重新实现,并被 many different applications 使用。有用的链接:Mozilla's coderesearch paper 它基于(讽刺的是,我的 Firefox 未能正确检测到该页面的编码)、short explanationdetailed explanation

【讨论】:

  • 哦哦。这正是我正在寻找的算法类型。现在,如果我能弄清楚它是如何工作的,或者只是找到一个 Delphi 等价物......
  • 根据文档,它是 Mozilla cpp 代码的 Python 端口。后者位于mxr.mozilla.org/seamonkey/source/extensions/universalchardet/… 不知道哪个化身更容易移植!
  • (续)CPP 版本的注释似乎更充分,这可能有助于移植。
  • 所有链接都失效了。您可以尝试恢复它们吗?
【解决方案2】:

【讨论】:

【解决方案3】:

我的猜测是:

  • 首先,检查文件的字节值是否小于 32(制表符/换行符除外)。如果是,则不能是 ANSI 或 UTF-8。因此 - UTF-16。只需要弄清楚字节序。为此,您可能应该使用一些有效的 Unicode 字符代码表。如果遇到无效代码,请尝试其他适合的字节序。如果适合(或不适合),请检查哪个具有较大百分比的字母数字代码。您也可以尝试搜索换行符并从中确定字节顺序。除此之外,我不知道如何检查字节顺序。
  • 如果文件不包含小于 32 的值(除了上述空格),它可能是 ANSI 或 UTF-8。尝试将其解析为 UTF-8 并查看是否有任何无效的 Unicode 字符。如果你这样做,它可能是 ANSI。
  • 如果您希望文档采用非英语单字节或多字节非 Unicode 编码,那么您就不走运了。您可以做的最好的事情是像 Internet Explorer 这样的东西,它制作字符值的直方图并将其与已知语言的直方图进行比较。它经常工作,但有时也会失败。而且您必须为每种语言拥有一个庞大的字母直方图库。

【讨论】:

  • 嗯,我经常在我的文本文件中看到值小于 32 的字节。诸如 \n、\r 和 \t 之类的东西。其他的也很少。
  • ASCII、大多数 ANSI 代码页和 UTF-8 都可以理解字节值小于 32 的字符,例如回车、换行、水平制表符、空字符等。
  • 我的意思是在问题中说 ANSI,而不是 ASCII。我现在修改了这个问题。您可能需要修改您的答案以反映这一点。
【解决方案4】:

ASCII?现代操作系统不再使用 ASCII。它们至少都使用 8 位代码,这意味着它可以是 UTF-8、ISOLatinX、WinLatinX、MacRoman、Shift-JIS 或其他任何代码。

我知道的唯一测试是检查无效的 UTF-8 字符。如果你找到了,那么你就知道它不可能是 UTF-8。 UTF-16 可能也是如此。但是当它没有设置 Unicode 时,就很难判断它可能是哪个 Windows 代码页。

我认识的大多数编辑器通过让用户从所有可能的编码列表中选择一个默认值来处理这个问题。

有用于检查 UTF 字符有效性的代码。

【讨论】:

  • Windows 仍然有设备驱动程序。如果你的内核代码不是 7 位干净的,你会后悔的。
  • @Windows 程序员:你的意思是内核代码需要 7 位干净?大多数(全部?)驱动程序需要处理 Unicode - 尽管有时问题是从 MBCS 正确转换为 Unicode(我使用 OEM 还是默认代码页?等等)。
  • 好的,处理文件名的代码必须复制和转换变量中的字符串(PUNICODE 等),但源代码仍然必须是 7 位干净才能在编译时正确编译。
猜你喜欢
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 2017-01-28
  • 2011-04-21
  • 2011-01-27
  • 1970-01-01
相关资源
最近更新 更多