如何可靠地猜测 MacRoman、CP1252、Latin1、UTF-8 和 ASCII 之间的编码您如何区分麦克罗曼和cp1252?

2022-08-31 10:09:37

在工作中,似乎没有一个星期过去了,没有一些与编码相关的纵容,灾难或灾难。问题通常源于程序员,他们认为他们可以可靠地处理“文本”文件而无需指定编码。但你不能。

因此,决定从此以后禁止文件具有以 或 结尾的名称。他们的想法是,这些扩展误导了临时程序员对编码的沉闷自满,这导致了不正确的处理。完全没有扩展名几乎会更好,因为至少这样你就知道你不知道你得到了什么。*.txt*.text

但是,我们并没有走那么远。相反,您将需要使用以编码结尾的文件名。因此,例如,对于文本文件,这些文件将类似于 , , 等。README.asciiREADME.latin1README.utf8

对于需要特定扩展名的文件,如果可以在文件本身内部指定编码,例如在Perl或Python中,那么您应该这样做。对于像Java源代码这样的文件,如果文件内部不存在这样的工具,您将在扩展名之前放置编码,例如.SomeClass-utf8.java

对于输出,UTF-8 是首选

但是对于输入,我们需要弄清楚如何处理名为 的代码库中的数千个文件。我们希望重命名所有这些名称以适应我们的新标准。但我们不可能把它们都看上去。因此,我们需要一个真正有效的库或程序。*.txt

这些在ASCII,ISO-8859-1,UTF-8,Microsoft CP1252或Apple MacRoman中各不相同。虽然我们知道我们可以判断某些东西是否是ASCII,并且我们知道某些东西是否可能是UTF-8,但我们对8位编码感到困惑。因为我们在混合的Unix环境(Solaris,Linux,Darwin)中运行,大多数桌面都是Mac,所以我们有相当多的烦人的MacRoman文件。这些尤其是一个问题。

一段时间以来,我一直在寻找一种方法来以编程方式确定哪种

  1. ASCII
  2. 国际标准-8859-1
  3. CP1252型
  4. 麦克罗曼
  5. UTF-8

一个文件在,我还没有找到一个程序或库,可以可靠地区分这三种不同的8位编码。我们可能只有一千多个MacRoman文件,因此无论我们使用什么字符集检测器,都必须能够嗅出这些文件。我看过的任何东西都无法做到这一点。我对ICU字符集检测器库抱有很大的希望,但它无法处理MacRoman。我也看过在Perl和Python中做同样事情的模块,但它总是一次又一次地讲述相同的故事:不支持检测MacRoman。

因此,我正在寻找的是一个现有的库或程序,它可以可靠地确定文件所在的这五种编码中的哪一种 , 最好是更多。特别是它必须区分我引用的三种3位编码,尤其是MacRoman。这些文件99%以上是英语文本;有一些其他语言,但不是很多。

如果它是库代码,我们的语言偏好是让它在Perl,C,Java或Python中,并且按照这个顺序。如果它只是一个程序,那么我们并不真正关心它是什么语言,只要它是完全源代码的,在Unix上运行,并且完全不受阻碍。

有没有其他人遇到过随机编码的大量遗留文本文件的问题?如果是这样,你是如何尝试解决它的,你有多成功?这是我的问题中最重要的方面,但我也有兴趣了解您是否认为鼓励程序员使用这些文件的实际编码来命名(或重命名)他们的文件将有助于我们避免将来的问题。有没有人试图在制度基础上执行这一点,如果是这样,这是否成功,为什么?

是的,我完全理解为什么考虑到问题的本质,人们不能保证一个明确的答案。对于小文件尤其如此,因为您没有足够的数据来继续。幸运的是,我们的文件很少很小。除了随机文件外,大多数都在50k到250k的大小范围内,许多都更大。任何超过几K的大小都可以保证是英文的。README

问题领域是生物医学文本挖掘,所以我们有时会处理广泛且非常大的语料库,就像PubMedCentral的所有开放获取存储库一样。一个相当大的文件是BioThesaurus 6.0,为5.7千兆字节。这个文件特别烦人,因为它几乎都是UTF-8。然而,一些麻木的骷髅在其中插入了几行8位编码 - 我相信微软CP1252。在你踏上那一条之前,需要相当长的时间。:(


答案 1

一、简单案例:

ASCII

如果您的数据不包含高于 0x7F 的字节,则为 ASCII。(或者7位ISO646编码,但这些已经非常过时了。

UTF-8

如果数据验证为 UTF-8,则可以安全地假定它是 UTF-8。由于 UTF-8 严格的验证规则,误报极为罕见。

ISO-8859-1 与视窗-1252

这两种编码之间的唯一区别是 ISO-8859-1 具有 C1 控制字符,而 windows-1252 具有可打印字符 €'ƒ“...†‡ˆ‰Š‹ŒŽ''”•–— ̃™š›œžŸ。我见过很多使用大引号或短划线的文件,但没有一个使用C1控制字符。因此,甚至不要打扰它们,或者ISO-8859-1,只需检测windows-1252即可。

现在,这只剩下一个问题。

您如何区分麦克罗曼和cp1252?

这要棘手得多。

未定义的字符

windows-1252 中不使用0x81、0x8D、0x8F、0x90 0x9D的字节。如果它们发生,则假设数据是MacRoman。

相同的字符

0xA2 (¢)、0xA3 (£)、0xA9 ()、0xB1 (©±) 0xB5 (μ) 的字节数在两种编码中恰好相同。如果这些是唯一的非 ASCII 字节,则选择 MacRoman 还是 cp1252 都无关紧要。

统计方法

计算您知道是 UTF-8 的数据中的字符(不是字节!)频率。确定最常用的字符。然后使用此数据来确定 cp1252 或 MacRoman 字符是否更常见。

例如,在我刚刚对100篇随机英语维基百科文章进行的搜索中,最常见的非ASCII字符是。基于这一事实,·•–é°®’èö—

  • 0x92、0x95、0x96、0x97、0xAE、0xB0、0xB7、0xE8、0xE9或0xF6表示 windows-1252 的字节。
  • 0x8E、0x8F、0x9A、0xA1、0xA5、0xA8、0xD0、0xD1、0xD5或0xE1的字节都表示为 MacRoman。

计算cp1252建议字节和MacRoman建议字节,并使用最大的字节。


答案 2

Mozilla nsUniversalDetector (Perl bindings: Encode::D etect/Encode::D etect::D etector) 是百万倍的证明。