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