5

Python 2.7 から Unicode テキストをロードする正しい方法は次のようになります。

content = open('filename').read().decode('encoding'):
for line in content.splitlines():
    process(line)

更新:いいえ、そうではありません。回答を参照してください。)

ただし、ファイルが非常に大きい場合は、一度に 1 行ずつ読み取ってデコードし、処理して、ファイル全体が一度にメモリに読み込まれないようにする必要があります。何かのようなもの:

for line in open('filename'):
    process(line.decode('encoding'))        

開いているファイルハンドルに対するforループの反復は、一度に 1 行ずつ読み取るジェネレーターです。

たとえば、ファイルが utf32 でエンコードされている場合、ファイル内のバイト (16 進数) は次のようになるため、これは機能しません。

hello\n = 68000000(h) 65000000(e) 6c000000(l) 6c000000(l) 6f000000(o) 0a000000(\n)

そして、forループによって行われる行への分割0aは、文字のバイトで分割され\n、結果は (16 進数で):

lines[0] = 0x 68000000 65000000 6c000000 6c000000 6f000000 0a
lines[1] = 0x 000000

したがって、\n文字の一部は 1 行目の最後に残り、残りの 3 バイトは 2 行目に残ります (2 行目に実際にあるテキストが続きますdecode) UnicodeDecodeError

UnicodeDecodeError: 'utf32' codec can't decode byte 0x0a in position 24: truncated data

したがって、明らかに、Unicode バイト ストリームを0aバイト単位で分割することは、それを行に分割する正しい方法ではありません。代わりに、完全な 4 バイトの改行文字 (0x0a000000) の発生で分割する必要があります。ただし、これらの文字を検出する正しい方法は、バイト ストリームを Unicode 文字列にデコードして文字を探すことだと思います\n。この完全なストリームのデコードは、まさに私が回避しようとしている操作です。

これは珍しい要件ではありません。それを処理する正しい方法は何ですか?

4

4 に答える 4

7

次のようなものを試してみてはどうですか:

for line in codecs.open("filename", "rt", "utf32"):
    print line

これはうまくいくはずだと思います。

codecsモジュールが翻訳を行う必要があります。

于 2012-08-08T14:27:27.140 に答える
4

codecs モジュールを使用してみてください:

for line in codecs.open(filename, encoding='utf32'):
    do_something(line)
于 2012-08-08T14:26:45.063 に答える
1

組み込みの open の代わりに codecs.open を使用します。

import codecs
for line in codecs.open('filename', encoding='encoding'):
    print repr(line)

http://docs.python.org/library/codecs.html#codecs.open

もちろん、慎重に作成したスタックオーバーフローの質問を終えた直後に、これを発見しました。

于 2012-08-08T14:27:27.657 に答える
1

codecs.openそれ自体io.openがより良いオプションであることに注意してください(注意はリンクターゲットのすぐ上にあります)。非推奨ではありませんが、難解な使用法 (bytes->bytes コーデック) をサポートしているからです。

io.openは Python 2.6 以降で利用可能で、Py3 のビルトイン と同じ動作を提供し、openより最適化されており、行末変換のようなものに関しては誤動作しませんcodecs.open。使用する唯一の理由codecs.openは、Python 2.5 以前をサポートする必要がある場合です。それ以外の場合io.openは、厳密に優れています。

import io

# Use with statement for guaranteed, predictable cleanup
with io.open('filename', encoding='utf-32') as f:
    for line in f:
        process(line)

ちなみに、すでに開いているバイナリ ファイルのようなオブジェクトは、を使用してシームレスなデコード テキスト ベースのオブジェクトに変換できます。そのため、他の誰かがバイナリ モードで既存のファイルのようなオブジェクトを提供した場合でも、行ごとのデコードを暗黙的に行うことができます。io.TextIOWrapper

def process_file(f):
    if 'b' in f.mode:  # Or some better test...
        f = io.TextIOWrapper(f, encoding='utf-32')
    for line in f:
        process(line)
于 2016-10-14T02:36:26.540 に答える