6

假设我在美国有一个 10GB 硬盘的 Ubuntu VPS(我住在其他地方),我在硬盘上有一个 9GB 的文本文件。我有 512MB 的 RAM,以及大约相同数量的交换。

鉴于我无法添加更多硬盘空间并且无法将文件移动到其他地方进行处理,是否有一种有效的方法可以使用 Python 从文件中删除一些行(最好,但任何其他语言都可以接受)?

4

5 回答 5

3

这个怎么样?它就地编辑文件。我已经在一些小文本文件(在 Python 2.6.1 中)上对其进行了测试,但我不确定它在大量文件上的性能如何,因为所有的跳跃,但仍然......

我使用了带有手动 EOF 检查的无限期 while 循环,因为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 )
于 2010-12-17T11:18:37.843 回答
2

试试这个:

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)

我还没有运行它,但想法是通过用要保留的行覆盖要删除的行来修改文件。我不确定查找和修改如何与文件的迭代交互。

于 2010-12-17T11:00:43.247 回答
1

更新

我通过创建一个 1GB 文件fileinput尝试就地。我所期望的与发生的不同。这次我正确地阅读了文档。

可选的就地过滤:如果关键字参数 inplace=1 被传递给 fileinput.input() 或 FileInput 构造函数,则文件被移动到备份文件并且标准输出被定向到输入文件(如果与备份文件同名的文件已存在,它将被静默替换)。

来自文档/文件输入

所以,这似乎不是你现在的选择。请检查其他答案。


编辑前:

如果您正在寻找就地编辑文件,请查看 Python 的fileinput模块 - Docs

我真的不确定它与 10gb 文件一起使用时的效率。但是,对我来说,这似乎是您使用 Python 的唯一选择。

于 2010-12-17T11:01:05.203 回答
0

只需按顺序读取和写入文件即可。

f.readlines() 返回一个包含文件中所有数据行的列表。如果给定一个可选参数 sizehint,它会从文件中读取那么多字节以及足够多的字节来完成一行,并从中返回这些行。这通常用于允许有效地逐行读取大文件,但不必将整个文件加载到内存中。只会返回完整的行。

来源

于 2010-12-17T10:41:59.743 回答
0

处理获得 10/20 或更多 MB 块的文件。这将是最快的方法。

其他方法是流式传输此文件并使用 AWK 对其进行过滤。

示例伪代码:

file = open(rw)
linesCnt=50
newReadOffset=0
tmpWrtOffset=0
rule=1
processFile()
{
  while(rule)
  {
      (lines,newoffset)=getLines(file, newReadOffset)
      if lines:
          [x for line in lines if line==cool: line]
          tmpWrtOffset = writeBackToFile(file, x, tmpWrtOffset) #should return new offset to write for the next time
      else:
          rule=0
  }
}

最后使用truncate(size=None)调整文件大小

于 2010-12-17T10:42:14.597 回答