我在打开文本文件以在文件内容中查找匹配项时遇到可变文本编码问题。
我正在编写一个脚本来扫描文件系统以查找具有特定内容的日志文件,以便将它们复制到存档中。名称经常更改,因此内容是识别它们的唯一方法。我需要识别 *.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 位。可能没有必要,但是 here is a sample log file .
编辑: 据我所知,这些文件几乎肯定会采用代码注释中的一种编码:ANSI、UTF-8、UTF_16_LE(如 UCS-2 LE w/o BOM;UCS-2 Little Endian)。总有可能有人找到绕过我期望的方法...
编辑: 虽然使用外部库肯定是合理的方法,但我有机会编写一些业余代码来猜测另一个问题中的编码和征求反馈 -> Pitfalls in my code for detecting text file encoding with Python?
请您参考如下方法:
chardet 包的存在是有原因的(出于类似的原因,它是从一些较旧的 Netscape 代码移植过来的):检测任意文本文件的编码很棘手。
有两种基本选择:
使用一些硬编码规则来确定文件是否具有特定编码。例如,您可以在文件开头查找 UTF 字节顺序标记。对于在使用不同字节时显着重叠的编码,或者对于不碰巧使用您的检测规则使用的“标记”字节的文件,这会中断。
获取已知编码文件的数据库,并计算每种编码中不同字节(以及字节对、三元组等)的分布。然后,当您有一个未知编码的文件时,对其字节进行采样并查看哪种字节使用模式最匹配。当您有较短的测试文件(这使得频率估计不准确),或者当您的测试文件中字节的使用与您用来构建频率数据的文件数据库中的使用不匹配时,这会中断。
notepad++ 可以进行字符检测(以及网络浏览器、文字处理器等)的原因是这些程序都内置了这些方法中的一种或两种。 Python 没有将其构建到其解释器中——它是一种通用编程语言,而不是文本编辑器——但这正是 chardet 包所做的。
我想说的是,因为您对正在处理的文本文件有所了解,所以您也许可以走一些捷径。例如,您的日志文件是否全部采用编码 A 或编码 B 之一?如果是这样,那么您的决定就简单多了,而且您自己实现上述基于频率或基于规则的方法可能会非常简单。但如果您需要检测任意字符集,我强烈建议您站在巨人的肩膀上构建。
