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()

エンコーディングを検出するメモ帳++でファイルを開くことができます。通常の file.open() Python コマンドを使用しても、エンコーディングは自動的に検出されません。codecs.open を使用し、エンコーディングを指定して単一のエンコーディングをキャッチすることはできますが、残りをキャッチするには余分なコードを記述する必要があります。Python codecs モジュールのドキュメントを読みましたが、自動検出がないようです。

任意のエンコーディングのテキスト ファイルを簡潔かつ確実に検索するには、どのようなオプションが必要ですか?

chardetモジュールについて読んだことがありますが、これは良さそうですが、モジュールのインストールを避ける必要があります。とにかく、古くて由緒あるテキスト ファイルを操作するためのより簡単な方法が必要です。確かに初心者として、私はこれを複雑にしすぎていますよね?

Python 2.7.2、Windows 7 64 ビット。おそらく必要ありませんが、サンプル ログ ファイルを次に示します

編集: 私の知る限り、ファイルはほぼ確実にコード コメントのエンコーディングのいずれかになります: ANSI、UTF-8、UTF_16_LE (BOM なしの UCS-2 LE、UCS-2 リトル エンディアン)。誰かが私の期待を回避する方法を見つける可能性は常にあります...

編集: 外部ライブラリを使用することは確かに健全なアプローチですが、別の質問でエンコーディングを推測し、フィードバックを求めたアマチュア コードを書く機会を得ました -> Python でテキスト ファイルのエンコーディングを検出するための私のコードの落とし穴?

4

1 に答える 1

1

パッケージが存在するのchardetには理由があります (同様の理由で、古い Netscape コードから移植されました)。任意のテキスト ファイルのエンコーディングを検出するのは難しいです。

2 つの基本的な代替手段があります。

  1. ハードコーディングされたルールを使用して、ファイルに特定のエンコーディングがあるかどうかを判断します。たとえば、ファイルの先頭にある UTF バイト オーダー マーカーを探すことができます。これは、異なるバイトの使用が大幅に重複するエンコーディング、または検出ルールで使用される「マーカー」バイトを使用しないファイルの場合に中断します。

  2. 既知のエンコーディングのファイルのデータベースを取得し、各エンコーディングの異なるバイト (およびバイト ペア、トリプレットなど) の分布を数えます。次に、不明なエンコーディングのファイルがある場合は、そのバイトのサンプルを取得し、どのパターンのバイト使用が最も一致するかを確認します。これは、テスト ファイルが短い (頻度の推定が不正確になる) 場合、またはテスト ファイル内のバイトの使用量が、頻度データの構築に使用したファイル データベース内の使用量と一致しない場合に壊れます。

notepad++ が (Web ブラウザ、ワード プロセッサなどと同様に) 文字検出を実行できる理由は、これらのプログラムにはすべて、これらのメソッドのいずれかまたは両方がプログラムに組み込まれているためです。Python はこれをインタープリターに組み込みません。これは汎用プログラミング言語であり、テキスト エディターではありません。しかし、それはまさにchardetパッケージが行うことです。

扱っているテキスト ファイルについて多少の知識があるので、いくつかの近道をすることができるかもしれません。たとえば、ログ ファイルはすべてエンコード A またはエンコード B のいずれかに含まれていますか? もしそうなら、決定ははるかに簡単で、おそらく上記の頻度ベースまたはルールベースのアプローチのいずれかを独自に実装するのは非常に簡単です. しかし、任意の文字セットを検出する必要がある場合は、巨人の肩の上に構築することを強くお勧めします。

于 2013-09-01T20:28:04.473 に答える