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)

如果您的行不需要都具有相同的长度,但是您可以绝对肯定这一新行与旧行的长度相同,您可以这样做:

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 回答