如何使用Python删除文件的最后一行?
输入文件示例:
hello
world
foo
bar
输出文件示例:
hello
world
foo
我已经创建了下面的代码来查找文件中的行数,但是我不知道如何删除特定的行号。
try:
file = open("file")
except IOError:
print "Failed to read file."
countLines = len(file.readlines())
如何使用Python删除文件的最后一行?
输入文件示例:
hello
world
foo
bar
输出文件示例:
hello
world
foo
我已经创建了下面的代码来查找文件中的行数,但是我不知道如何删除特定的行号。
try:
file = open("file")
except IOError:
print "Failed to read file."
countLines = len(file.readlines())
由于我经常处理几个GB大小的文件,像答案中提到的那样循环遍历对我没有用。我使用的解决方案是:
with open(sys.argv[1], "r+", encoding = "utf-8") as file:
# Move the pointer (similar to a cursor in a text editor) to the end of the file
file.seek(0, os.SEEK_END)
# This code means the following code skips the very last character in the file -
# i.e. in the case the last line is null we delete the last line
# and the penultimate one
pos = file.tell() - 1
# Read each character in the file one at a time from the penultimate
# character going backwards, searching for a newline character
# If we find a new line, exit the search
while pos > 0 and file.read(1) != "\n":
pos -= 1
file.seek(pos, os.SEEK_SET)
# So long as we're not at the start of the file, delete all the characters ahead
# of this position
if pos > 0:
file.seek(pos, os.SEEK_SET)
file.truncate()
"a+"
而不是"r+"
打开文件,你可以跳过file.seek(0, os.SEEK_END)
吗? - TheLizzard您可以使用上面的代码,然后:
lines = file.readlines()
lines = lines[:-1]
这将给你一个包含除最后一行外的所有行的数组。os.system("sed '$d' file")
来运行sed
,在处理大文件和一般处理时,使用二进制文件会更快。截断文件似乎是最快的方法。无论如何,这个问题有很多有用的选项 :) +1 对这个问题。 - m3nda这不是Python语言,但如果你只需要执行这个任务的话,Python并不是最适合的工具。你可以使用标准的*nix实用程序head
来完成。
head -n-1 filename > newfile
这将复制除了文件名的最后一行以外的所有内容到新文件中。
seek
的Python版本对内存的需求较小,因此更适合处理非常大的文件,而head
是一个不错的一行代码,但涉及读取和复制几乎整个文件。 - Marie Hoffmannlast_line = None
for line in file:
if last_line:
print last_line # or write to a file, call a function, etc.
last_line = line
这不是世界上最优美的代码,但它能完成工作。
基本上,它通过 last_line 变量缓冲文件中的每一行,每次迭代输出前一次迭代的行。
这是我为Linux用户提供的解决方案:
import os
file_path = 'test.txt'
os.system('sed -i "$ d" {0}'.format(file_path))
file = open('file.txt', 'rb')
pos = next = 0
for line in file:
pos = next # position of beginning of this line
next += len(line) # compute position of beginning of next line
file = open('file.txt', 'ab')
file.truncate(pos)
根据我的测试,当按行读取时,file.tell()不起作用,可能是由于缓冲区混淆了它。这就是为什么要通过累加行的长度来确定位置。请注意,这仅适用于行分隔符以'\n'结尾的系统。
这里有一个更通用的内存高效解决方案,允许跳过最后的'n'行(就像head
命令):
import collections, fileinput
def head(filename, lines_to_delete=1):
queue = collections.deque()
lines_to_delete = max(0, lines_to_delete)
for line in fileinput.input(filename, inplace=True, backup='.bak'):
queue.append(line)
if lines_to_delete == 0:
print queue.popleft(),
else:
lines_to_delete -= 1
queue.clear()
with open('file_name', 'r+') as f:
f.seek(0, os.SEEK_END)
while f.tell() and f.read(1) != '\n':
f.seek(-2, os.SEEK_CUR)
f.truncate()
这里是另一种方法,不需要将整个文件读入内存
p=""
f=open("file")
for line in f:
line=line.strip()
print p
p=line
f.close()
虽然我没有测试过它(请不要因此而讨厌我),但我相信有一种更快的方法。这更像是C语言的解决方案,但在Python中也很可能实现。它也不是Pythonic的,只是一种理论上的想法。
首先,你需要知道文件的编码方式。将一个变量设置为该编码方式中每个字符使用的字节数(ASCII中为1个字节)。我们可以称之为CHARsize。对于ASCII文件,这个值通常为1个字节。
然后获取文件的大小,并将其设置为FILEsize。
假设你已经拥有了文件的地址(在内存中)FILEadd。
将FILEsize加到FILEadd中。
向后移动(每次增加-1***CHARsize**),并测试每个CHARsize字节是否为\n(或者你的系统使用的任何换行符)。当你到达第一个\n时,你现在就知道了文件第一行的开头位置。将\n替换为\x1a(26,EOF的ASCII码,或者根据你的系统/编码方式替换为其他字符)。
按照您的需要进行清理(更改文件大小,触摸文件等)。
如果这个方法像我预想的那样有效,您将会节省很多时间,因为您不需要从头开始读取整个文件,而是从结尾开始读取。