0

Bonjour Stack0verflow

stored_outputこのコードを取得して、 1 行目 (タイトル行) なしでデータを書き込もうとしています。

私が試したこと:

with open(filenamex, 'rb') as currentx:
    current_data = currentx.read()
    ## because of my filesize I dont want to go through each line the the route shown below to remove the first line (title row)
    for counter, line in enumerate(current_data):
        if counter != 0:
            data.writeline(line)
    #stored_output.writelines(current_data)

ファイルサイズのため、for ループを実行したくありません (効率)

建設的なコメントやコード スニペットをいただければ幸いです。
ありがとうAEA

4

2 に答える 2

9

ファイル反復子で使用next()して、最初の行をスキップし、次を使用して残りのコンテンツを書き込むことができfile.writelinesます。

with open(filenamex, 'rb') as currentx, open('foobar', 'w') as data:
    next(currentx)            #drop the first line
    data.writelines(currentx) #write rest of the content to `data`

注:file.read()ファイルを 1 行ずつ読み取りたい場合は使用しないでください。ファイル オブジェクトを反復処理して一度に 1 行ずつ取得してください。

于 2013-11-01T00:50:06.287 に答える
6

最初の問題は、currentx.read()1 つの巨大な文字列を返すことです。そのため、それをループすると、ファイル内の各行ではなく、その文字列内の各文字がループされます

次のように、ファイルを文字列の巨大なリストとしてメモリに読み込むことができます。

current_data = list(currentx)

ただし、これは、一度に 1 行ずつファイルを反復処理するより (Python に適切なサイズのバッファーを選択させるのではなく、ファイル全体にメモリを割り当てるのに時間を浪費するため)、ファイル全体を一度に処理するよりも遅くなることがほぼ保証されています (行を分割するのに時間を無駄にしているからです)。言い換えれば、この方法では両方の世界で最悪の事態が発生します。

したがって、行のイテレータとして保持するか:

next(currentx) # skip a line
for line in currentx:
    # do something with each line

…または文字列として保持し、最初の行を分割します。

current_data = currentx.read()
first, _, rest = current_data.partition('\n')
# do something with rest

一度にファイルを読み書きするのが遅すぎることが判明した場合はどうなるでしょうか (これはおそらく、書き込み前に初期ブロックを強制的にキャッシュから追い出し、インターリーブを防ぎ、メモリの割り当てに時間を無駄にします)。一度に実行するの遅すぎます (可能性は低いですが、不可能ではありません。改行の検索、小さな文字列のコピー、および Python でのループは無料ではありません。CPU 時間は I/O 時間よりもはるかに安いため、めったに重要ではありません)?

あなたができる最善の方法は、理想的なブロックサイズを選択し、バッファリングされていない読み取りと書き込みを自分で行い、最初の改行が見つかるまで時間を無駄にするだけです。

最初の行がブロック サイズよりも長くならないと仮定できる場合、これは非常に簡単です。

BLOCK_SIZE = 8192 # a usually-good default--but if it matters, test
with open(inpath, 'rb', 0) as infile, open(outpath, 'wb', 0) as outfile:
    buf = infile.read(BLOCK_SIZE)
    first, _, rest = buf.partition(b'\n')
    outfile.write(rest)
    while True:
        buf = infile.read(BLOCK_SIZE)
        if not but:
            break
        outfile.write(buf)

これを複数回行う場合は、ブロック ファイル イテレータ関数を作成します (または、事前にテスト済みのレシピを探したほうがよいでしょう。それらは ActiveState やメーリング リストのいたるところにあります)。

于 2013-11-01T00:51:23.270 に答える