我在Linux系统上使用非常大的(~11GB)文本文件。我正在通过检查文件错误的程序运行它。一旦发现错误,我需要修复该行或完全删除该行。然后重复......
最终,一旦我对这个过程感到满意,我会完全自动完成它。但是现在,让我们假设我手动运行它。
从这个大文件中删除特定行的最快(在执行时间方面)是什么?我想在Python中做到这一点......但是会对其他例子持开放态度。该行可能是文件中的任何地方。
如果是Python,请假设以下界面:
def removeLine(filename, lineno):
谢谢,
-AJ
答案 0 :(得分:13)
同一个文件可以有两个文件对象(一个用于阅读,一个用于写入):
def removeLine(filename, lineno):
fro = open(filename, "rb")
current_line = 0
while current_line < lineno:
fro.readline()
current_line += 1
seekpoint = fro.tell()
frw = open(filename, "r+b")
frw.seek(seekpoint, 0)
# read the line we want to discard
fro.readline()
# now move the rest of the lines in the file
# one line back
chars = fro.readline()
while chars:
frw.writelines(chars)
chars = fro.readline()
fro.close()
frw.truncate()
frw.close()
答案 1 :(得分:7)
修改文件到位,违规行被替换为空格,因此文件的其余部分不需要在磁盘上进行随机播放。如果修复不长于您要替换的行,您还可以“修复”该行
import os
from mmap import mmap
def removeLine(filename, lineno):
f=os.open(filename, os.O_RDWR)
m=mmap(f,0)
p=0
for i in range(lineno-1):
p=m.find('\n',p)+1
q=m.find('\n',p)
m[p:q] = ' '*(q-p)
os.close(f)
如果可以更改其他程序以输出文件偏移而不是行号,则可以直接将偏移量分配给p并且不使用for循环
答案 2 :(得分:1)
据我所知,你不能只用python打开一个txt文件并删除一行。您必须创建一个新文件并将除此行之外的所有内容移动到该文件中。如果你知道具体的行,那么你会做这样的事情:
f = open('in.txt')
fo = open('out.txt','w')
ind = 1
for line in f:
if ind != linenumtoremove:
fo.write(line)
ind += 1
f.close()
fo.close()
您当然可以检查该行的内容,以确定是否要保留该行。我还建议如果您要删除/更改完整行列表,以便在一次传递文件中执行所有这些更改。
答案 3 :(得分:1)
如果这些行是可变长度的,那么我不相信有一个比逐行读取文件和写出所有行更好的算法,除了你不想要的那些行。
您可以通过检查某些条件来识别这些行,或者通过保持读取行的运行计数并禁止写入您不想要的行。
如果行是固定长度而你想删除特定的行号,那么你可以使用seek
来移动文件指针......我怀疑你是那么幸运。
答案 4 :(得分:1)
更新:解决方案中海报要求使用sed解决方案。
删除例如第二行文件:
sed '2d' input.txt
使用-i
开关进行编辑。警告:这是一种破坏性操作。请阅读此命令的帮助,以获取有关如何自动进行备份的信息。
答案 5 :(得分:0)
def removeLine(filename, lineno):
in = open(filename)
out = open(filename + ".new", "w")
for i, l in enumerate(in, 1):
if i != lineno:
out.write(l)
in.close()
out.close()
os.rename(filename + ".new", filename)
答案 6 :(得分:0)
我认为这里提出的问题有点类似,如果不完全相同。逐行读取(和写入)很慢,但是您可以一次读取更大的块到内存中,逐行跳过您不想要的行,然后将其作为单个块写入新文件。重复直到完成。最后用新文件替换原始文件。
需要注意的是,当你读入一个块时,你需要处理你读取的最后一个可能是部分的行,然后将它添加到你读到的下一个块中。
答案 7 :(得分:0)
@OP,如果你可以使用awk,例如假设行号为10
$ awk 'NR!=10' file > newfile
答案 8 :(得分:0)
我将根据查找因子(行号或搜索字符串)提供两种备选方案:
def removeLine2(filename, lineNumber):
with open(filename, 'r+') as outputFile:
with open(filename, 'r') as inputFile:
currentLineNumber = 0
while currentLineNumber < lineNumber:
inputFile.readline()
currentLineNumber += 1
seekPosition = inputFile.tell()
outputFile.seek(seekPosition, 0)
inputFile.readline()
currentLine = inputFile.readline()
while currentLine:
outputFile.writelines(currentLine)
currentLine = inputFile.readline()
outputFile.truncate()
def removeLine(filename, key):
with open(filename, 'r+') as outputFile:
with open(filename, 'r') as inputFile:
seekPosition = 0
currentLine = inputFile.readline()
while not currentLine.strip().startswith('"%s"' % key):
seekPosition = inputFile.tell()
currentLine = inputFile.readline()
outputFile.seek(seekPosition, 0)
currentLine = inputFile.readline()
while currentLine:
outputFile.writelines(currentLine)
currentLine = inputFile.readline()
outputFile.truncate()