0

n行目を置き換えたい大きなファイルがあるとします。私はこの解決策を知っています:

w = open('out','w')
for line in open('in','r'):
    w.write(replace_somehow(line))

os.remove('in')
os.rename('out','in')

ファイルの先頭に置換する行がある場合、ファイル全体を多くの行で書き換えたくありません。n行目を直接置き換える適切な可能性はありますか?

4

1 に答える 1

6

新しい行が元の行とまったく同じ長さであることが保証されない限り、ファイル全体を書き換える方法はありません。


一部のワード プロセッサは、変更のジャーナル、各チャンクの最後に余分なスペースがあるチャンクの大きなリスト、または小さなチャンクのデータベースを保存することで、非常に凝っています。ジャーナリング、または単一のチャンクの書き換え、またはデータベースの更新を行います)、しかし実際の「保存」ボタンはファイル全体を再構築し、一度にすべて書き込みます。

これは、ユーザーが手動で保存するよりも頻繁に自動保存する場合や、ファイルが非常に大きい場合に行う価値があります。(たとえば、Microsoft Word が設計されたとき、100KB は非常に大きかったことを覚えておいてください…)


そして、これは正しい答えを示しています。5GB のデータがあり、その中の N 番目のレコードを変更する必要がある場合、インデックスのない一連の可変長レコードとして定義されている形式を使用しないでください。これがテキストファイルです。あなたの場合に適した最も単純な形式は固定サイズのレコードのシーケンスですが、レコードを挿入または削除したり、その場で変更したりする必要がある場合は、テキスト ファイルと同じように問題があります。したがって、まず要件を検討してから、データ構造を選択してください。

他のプログラムと交換するために、より制限された形式 (テキスト ファイルなど) を処理する必要がある場合は、問題ありません。すべての変更を行った後、ファイル全体を一度書き直して「エクスポート」する必要がありますが、変更を加えるたびに行う必要はありません。


すべての行がまったく同じ長さである場合は、次のように実行できます。

with open('myfile.txt', 'rb+') as f:
    f.seek(FIXED_LINE_LENGTH * line_number)
    f.write(new_line)

重要なのはバイト単位の長さであり、文字単位の長さではないことに注意してください。この方法で使用するには、ファイルをバイナリ モードで開く必要があります。


置き換えようとしている行番号がわからない場合は、次のようにする必要があります。

with open('myfile.txt', 'rb+') as f:
    for line_number, line in enumerate(f):
        if is_the_right_line(line):
            f.seek(FIXED_LINE_LENGTH * line_number)
            f.write(new_line)

すべての行が同じ長さである必要はないが、この 1 つの新しい行が古い行と同じ長さであることを完全に確信できる場合は、次のようにすることができます。

with open('myfile.txt', 'rb+') as f:
    last_pos = 0
    for line_number, line in enumerate(f):
        if is_the_right_line(line):
            f.seek(last_pos)
            f.write(new_line)
        last_pos = f.tell()
于 2013-04-24T22:42:50.130 に答える