如何可靠地猜测MacRoman、CP1252、Latin1、UTF-8和ASCII之间的编码

2024-09-26 22:49:22 发布

您现在位置:Python中文网/ 问答频道 /正文

在工作中,似乎没有一个星期没有编码相关的连接、灾难或灾难。这个问题通常源于程序员,他们认为自己可以在不指定编码的情况下可靠地处理“文本”文件。但你不能

因此决定从此禁止文件的名称以*.txt*.text结尾。这种想法是,这些扩展误导了普通程序员,使他们在编码方面变得沉闷自满,这导致了不正确的处理。最好没有 扩展,因为至少你知道你不知道你有什么。

不过,我们不会走那么远。相反,您需要使用以编码结尾的文件名。例如,对于文本文件来说,这些文件应该是README.asciiREADME.latin1README.utf8

对于需要特定扩展名的文件,如果可以在文件本身中指定编码,例如在Perl或Python中,则应该这样做。对于像Java source这样在文件内部不存在这种功能的文件,您将把编码放在扩展名之前,例如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. ISO-8859-1标准
  3. CP1252型
  4. 马克西曼
  5. UTF-8型

文件在中,我还没有找到一个程序或库可以可靠地区分这三种不同的8位编码。光是MacRoman文件就有一千多个,所以我们使用的任何字符集检测器都必须能够嗅出这些文件。我看过的任何东西都无法应付这个把戏。我对ICU charset detector library寄予厚望,但它无法处理MacRoman。我还研究了在Perl和Python中做同样事情的模块,但一次又一次总是相同的情况:不支持检测MacRoman。

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

如果它是库代码,我们的语言偏好是以Perl、C、Java或Python为单位,并按顺序排列。如果它只是一个程序,那么只要它有完整的源代码,在Unix上运行,并且完全没有负担,我们就不在乎它是什么语言。

有没有其他人有过这样的问题:无数的传统文本文件是随机编码的?如果是的话,你是怎么解决的,你有多成功?这是我问题中最重要的方面,但我也感兴趣的是,你是否认为鼓励程序员用这些文件的实际编码来命名(或重命名)他们的文件,将有助于我们在将来避免这个问题。有没有人试图在制度基础上强制执行,如果是,那么是否成功,为什么?

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

问题的领域是生物医学文本挖掘,因此我们有时会处理大量和非常大的语料库,就像所有PubMedCentral的开放存取存储库一样。一个相当大的文件是BioThesaurus 6.0,5.7gb。这个文件特别烦人,因为它几乎都是UTF-8。但是,我相信,一些numbskull在其中插入了一些8位编码的微软CP1252代码。你花了很长时间才去看那个。:(一)


Tags: 文件代码文本程序语言编码ascii情况
3条回答

首先,简单的案例:

ASCII码

如果您的数据不包含高于0x7F的字节,那么它是ASCII。(或7位ISO646编码,但这些都是非常过时的。)

UTF-8型

如果您的数据验证为UTF-8,那么您可以安全地假设它UTF-8。由于UTF-8的严格验证规则,误报非常罕见。

ISO-8859-1与windows-1252

这两种编码之间的唯一区别是,ISO-8859-1具有C1控制字符,而windows-1252具有可打印字符™š›œžŸ. 我见过很多使用花引号或破折号的文件,但没有一个使用C1控制字符。所以甚至不用麻烦他们,或者ISO-8859-1,只需检测windows-1252。

现在只剩下一个问题了。

如何区分MacRoman和cp1252?

这要复杂得多。

未定义字符

字节0x81、0x8D、0x8F、0x90、0x9D不在windows-1252中使用。如果它们发生了,那么假设数据是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的建议字节数加起来,取最大值。

Mozilla nsUniversalDetector(Perl绑定:Encode::Detect/Encode::Detect::Detector)已经被证明是百万倍。

我尝试这样一种启发式方法(假设您已经排除了ASCII和UTF-8):

  • 如果0x7f到0x9f根本就没有出现,那么很可能是ISO-8859-1,因为这些是很少使用的控制代码。
  • 如果0x91到0x94出现在lot中,那么很可能是Windows-1252,因为这些是“智能引号”,是该范围内最有可能在英语文本中使用的字符。更确切地说,你可以找对。
  • 否则,就是MacRoman,特别是当你看到大量的0xd2到0xd5(这就是MacRoman中的印刷引号)。

旁注:

For files like Java source where no such facility exists internal to the file, you will put the encoding before the extension, such as SomeClass-utf8.java

不要这样做!!

Java编译器希望文件名与类名匹配,因此重命名文件将使源代码不可编译。正确的做法是猜测编码,然后使用^{}工具将所有非ASCII字符转换为Unicode escape sequences

相关问题 更多 >

    热门问题