3

在打开文本文件以在文件内容中查找匹配项时,我遇到了可变文本编码的问题。

我正在编写一个脚本来扫描文件系统以查找具有特定内容的日志文件,以便将它们复制到存档中。名称经常更改,因此内容是识别它们的唯一方法。我需要识别 *.txt 文件并在其内容中找到这些特定日志文件唯一的字符串。

我有下面的代码,大部分都有效。问题是如果打开和编辑日志,它们的编码可能会发生变化。在这种情况下,Python 不会将搜索词与内容匹配,因为当 Python 使用错误的编码打开文件时,内容会出现乱码。

import os
import codecs

#Filepaths to search
FILEPATH = "SomeDrive:\\SomeDirs\\"

#Text to match in file names
MATCH_CONDITION = ".txt"

#Text to match in file contents
MATCH_CONTENT = "--------Base Data Details:--------------------"

for root, dirs, files in os.walk(FILEPATH):
    for f in files:
        if MATCH_CONDITION in f:
            print "Searching: "  + os.path.join(root,f)

            #ATTEMPT A -
            #matches only text file re-encoded as ANSI,
            #UTF-8, UTF-8 no BOM

            #search_file = open(os.path.join(root,f), 'r')

            #ATTEMPT B -
            #matches text files ouput from Trimble software
            #"UCS-2 LE w/o BOM", also "UCS-2 Little Endian" -
            #(same file resaved using Windows Notepad),

            search_file = codecs.open(os.path.join(root,f), 'r', 'utf_16_le')


            file_data = search_file.read()

            if MATCH_CONTENT in file_data:
                print "CONTENTS MATCHED: " + f

            search_file.close()

我可以在检测编码的 Notepad ++ 中打开文件。使用常规 file.open() Python 命令不会自动检测编码。我可以使用 codecs.open 并指定编码来捕获单个编码,但随后必须编写多余的代码来捕获其余部分。我已经阅读了 Python 编解码器模块文档,它似乎没有任何自动检测。

我有什么选择可以简洁有力地搜索任何编码的文本文件?

我已经阅读了有关chardet模块的信息,这看起来不错,但我确实需要避免安装模块。无论如何,必须有更简单的方式与古老而古老的文本文件进行交互。当然,作为一个新手,我把这弄得太复杂了,对吧?

Python 2.7.2,Windows 7 64 位。可能没有必要,但这里有一个示例日志文件

编辑: 据我所知,这些文件几乎肯定会采用代码注释中的一种编码:ANSI、UTF-8、UTF_16_LE(作为 UCS-2 LE w/o BOM;UCS-2 Little Endian)。总有可能有人找到解决我期望的方法......

编辑: 虽然使用外部库肯定是正确的方法,但我有机会编写一些业余代码来猜测编码并在另一个问题中征求反馈 - >我的代码中的陷阱用于检测使用 Python 的文本文件编码?

4

1 回答 1

1

这个chardet包的存在是有原因的(并且是从一些旧的 Netscape 代码中移植过来的,出于类似的原因):检测任意文本文件的编码是很棘手的。

有两种基本选择:

  1. 使用一些硬编码规则来确定文件是否具有某种编码。例如,您可以在文件开头查找 UTF 字节顺序标记。这会破坏在使用不同字节时显着重叠的编码,或者对于没有碰巧使用检测规则使用​​的“标记”字节的文件。

  2. 获取一个已知编码的文件数据库,并计算每种编码中不同字节(以及字节对、三元组等)的分布。然后,当您有一个未知编码的文件时,对其字节进行采样并查看哪种字节使用模式最匹配。当您有较短的测试文件(这使得频率估计不准确),或者当您的测试文件中字节的使用与您用于构建频率数据的文件数据库中的使用不匹配时,这会中断。

notepad++ 可以进行字符检测(以及网络浏览器、文字处理器等)的原因是这些程序都在程序中内置了这些方法中的一种或两种。Python 没有将它构建到它的解释器中——它是一种通用编程语言,而不是文本编辑器——但这正是chardet包的作用。

我会说,因为您知道一些关于您正在处理的文本文件的事情,所以您可以采取一些捷径。例如,您的日志文件是否全部采用编码 A 或编码 B 之一?如果是这样,那么您的决定要简单得多,并且可能上述基于频率或基于规则的方法都可以非常简单地由您自己实施。但是,如果您需要检测任意字符集,我强烈建议您建立在巨人的肩膀上。

于 2013-09-01T20:28:04.473 回答