假设我有一个大文件,我想替换第n行。我知道这个解决方案:
w = open('out','w')
for line in open('in','r'):
w.write(replace_somehow(line))
os.remove('in')
os.rename('out','in')
如果要在文件开头替换的行,我不想用多行重写整个文件。 是否有可能直接替换第n行?
答案 0 :(得分: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()