【问题标题】:Searching text files' contents with various encodings with Python?使用 Python 搜索具有各种编码的文本文件的内容?
【发布时间】:2013-09-01 19:46:47
【问题描述】:

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

我正在编写一个脚本来扫描文件系统以查找具有特定内容的日志文件,以便将它们复制到存档中。名称经常更改,因此内容是识别它们的唯一方法。我需要识别 *.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

编辑: 据我所知,这些文件几乎肯定会采用代码 cmets 中的一种编码: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?

【问题讨论】:

标签: python python-2.7 encoding text-files


【解决方案1】:

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

有两种基本的选择:

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

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

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

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

【讨论】:

  • 应该只有一些可能的编码包含在您的问题提示的编辑中。这确实比我意识到的要复杂得多。感谢您深思熟虑的答复,这是我读到的关于此事的最清楚的答复。
猜你喜欢
  • 2014-12-14
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-12
  • 2017-09-10
  • 2012-12-01
  • 2012-07-27
相关资源
最近更新 更多