0

ファイル内のすべての行を反復処理する関数が必要です。
これが私がこれまでに持っているものです:

def LineFeed(file):
    ret = ""
    for byte in file:
        ret = ret + str(byte)
        if str(byte) == '\r':
            yield ret
            ret = ""

ファイル内のすべての行は \r (\n ではありません) で終わり、"rb" モードで読み込んでいます (このファイルをバイナリで読み込む必要があります)。yield動作せず、何も返されません。問題がある可能性があります。 Pythonでバイト/文字をどのように表現するかわかりません。

「rb」ファイルでforループを実行すると、バイトではなく行を反復しようとするという考えが得られます...どうすればバイトを反復できますか? 私の問題は、標準の行末がないことです。また、私のファイルは0x00バイトでいっぱいで、それらをすべて取り除きたいので、2番目のyield関数が必要だと思います.どうすればそれを実装できますか.Pythonで0x00バイトを表現する方法がわかりません.またはNULL文字。

4

5 に答える 5

2

「for x in file」が何をするのか混乱していると思います。「file = open(file_name)」のようなハンドルを取得したと仮定すると、この場合のバイトは 1 文字ではなく行全体になります。したがって、行全体が単一の改行で構成されている場合にのみ、yield を呼び出しています。「バイト」を「行」に変更し、2 番目のループでそれを繰り返してみてください。

于 2009-12-17T22:31:32.247 に答える
1

ファイルを開く方法を制御している場合は、普遍的な改行で開くことをお勧めします。これは、「rb」モードを使用するだけでは \r が改行文字として認識されないためです。アーブ」。

汎用改行を使用すると \r と \n の区別が失われるため、バイナリ ファイルのどこかに \r だけでなく \n も含めていない場合にのみ機能します。

生成された行を \r で終了させたいと仮定すると、次のようになります。

NUL = '\x00'
def lines_without_nulls(path):
    with open(path, 'Urb') as f:
        for line in f:
            yield line.replace(NUL, '').replace('\n', '\r')
于 2009-12-18T02:36:13.053 に答える
0

したがって、問題は'\r'、行区切りとして使用するバイナリ モードで開いているファイルの行を反復処理することです。ファイルはバイナリ モードであるため、ユニバーサル改行機能を使用することはできず、バイナリ モードで'\r'は行区切りとして解釈されないことがわかります。

ファイルを char ごとに読み取ることは、Python で行うには非常に非効率的ですが、行を反復処理する方法は次のとおりです。

def cr_lines(the_file):
    line = []
    while True:
        byte = the_file.read(1)
        if not byte:
            break
        line.append(byte)
        if byte == '\r':
            yield ''.join(line)
            line = []
    if line:
        yield ''.join(line)

より効率的にするには、より大きなテキストのチャンクを読み取り、反復子でバッファリングを処理する必要があります。繰り返しながらシークすると、奇妙なバグが発生する可能性があることに注意してください。これらのバグを防ぐには、ファイルのサブクラスが必要になるため、シーク時にバッファーをパージできます。

''.join(line)イディオムの使用に注意してください。で文字列を累積すると+=パフォーマンスが低下し、初心者のプログラマーがよく犯す間違いです。

于 2009-12-17T23:06:37.453 に答える
0

編集:

  • string1 += string2文字列連結が遅い。文字列のリストを結合してみてください。

  • structddaa は正しいです。バイナリ ファイルに ASCII しか含まれていない場合は、パッケージは必要ありません。また、私のジェネレーターは、最後の '\r' の後、EOF の前に文字列を返します。これら 2 つのマイナーな修正により、私のコードはこの最近の回答と疑わしいほど似ています (実質的に同一です) 。

コードスニップ:

def LineFeed(f):
    ret = []
    while True:
        oneByte = f.read(1)
        if not oneByte: break
        # Return everything up to, but not including the carriage return
        if oneByte == '\r':
            yield ''.join(ret)
            ret = []
        else:
            ret.append(oneByte)
    if oneByte:
        yield ''.join(ret)
if __name__ == '__main__':
    lf = LineFeed( open('filename','rb') )

    for something in lf:
        doSomething(something)
于 2009-12-17T22:35:35.960 に答える