如何在有限环境下用Python删除大文件中的行
假设我在美国有一个10GB的硬盘驱动器(HDD)虚拟私人服务器(VPS),而我住在其他地方。我的硬盘上有一个9GB的文本文件。我有512MB的内存,还有差不多同样大小的交换空间。
考虑到我不能增加硬盘空间,也不能把文件移动到其他地方处理,有没有什么有效的方法可以用Python(最好是这样,但其他语言也可以)来删除文件中的某些行呢?
5 个回答
更新:
我尝试使用 fileinput
模块的 inplace 功能,创建了一个1GB的文件。我原本期待的结果和实际发生的情况不一样。这次我仔细阅读了文档。
可选的就地过滤:如果在调用
fileinput.input()
或FileInput
构造函数时传入关键字参数inplace=1
,那么文件会被移动到一个备份文件中,标准输出会被重定向到输入文件(如果已经存在一个与备份文件同名的文件,它会被静默替换)。
所以,这似乎现在不是你的选项。请查看其他答案。
编辑前:
如果你想要对文件进行 就地 编辑,可以看看Python的 fileinput
模块 - 文档。
我对它在处理10GB文件时的效率并不确定。不过,对我来说,这似乎是你在使用Python时唯一的选择。
试试这个:
currentReadPos = 0
removedLinesLength = 0
for line in file:
currentReadPos = file.tell()
if remove(line):
removedLinesLength += len(line)
else:
file.seek(file.tell() - removedLinesLength)
file.write(line + "\n")
file.flush()
file.seek(currentReadPos)
我没有实际运行过这个代码,但它的思路是直接在文件里修改,把你想删除的行用你想保留的行覆盖掉。我不太确定在修改文件的时候,如何处理文件的读取和修改之间的关系。
这样怎么样?这个方法可以直接在文件中进行编辑。我在一些小的文本文件上测试过(使用的是Python 2.6.1),不过我不太确定在处理大文件时效果如何,因为会有很多跳来跳去的操作,但总的来说……
我用了一个无限循环,并手动检查文件是否到达末尾,因为用 for line in f:
这个写法不太好用(可能是因为跳来跳去的操作搞乱了正常的遍历)。可能还有更好的方法来检查这个,但我对Python还比较陌生,所以如果有更好的方法,请大家告诉我。
另外,你需要定义一个函数 isRequired(line)
。
writeLoc = 0
readLoc = 0
with open( "filename" , "r+" ) as f:
while True:
line = f.readline()
#manual EOF check; not sure of the correct
#Python way to do this manually...
if line == "":
break
#save how far we've read
readLoc = f.tell()
#if we need this line write it and
#update the write location
if isRequired(line):
f.seek( writeLoc )
f.write( line )
writeLoc = f.tell()
f.seek( readLoc )
#finally, chop off the rest of file that's no longer needed
f.truncate( writeLoc )