📅  最后修改于: 2023-12-03 14:53:37.057000             🧑  作者: Mango
在编写程序时,我们有时需要处理很大的文件。然而,直接读取整个文件可能会导致内存不足的问题。在这种情况下,只需要读取文件的最后几行,就可以解决问题了。本文将介绍几种实现方式,帮助程序员解决读取大文件的最后n行的问题。
def tail(filename, n):
with open(filename) as f:
# 将文件指针移动到文件末尾
f.seek(0, 2)
# 获取文件大小
total_bytes = f.tell()
size = min(n, total_bytes)
# 将文件指针移动到倒数第n行行首
f.seek(-size, 2)
lines = f.readlines()
# 处理行末的换行符
for i in range(-1, -len(lines)-1, -1):
if lines[i][-1] == '\n':
lines[i] = lines[i][:-1]
return lines[-n:]
方法介绍:首先,使用f.seek(0, 2)
将文件指针移动到文件末尾,然后通过f.tell()
获取文件大小,将文件指针移动到倒数第n行行首,使用f.readlines()
读取文件的剩余部分,最后返回最后n行。如果行末有换行符,则需要去除。这种方式适用于读取文本文件,但是对于二进制文件则需要进行手动处理。
优点:代码简单,适用于读取文本文件。
缺点:不适用于读取二进制文件。
tail -n 10 filename
方法介绍:在Linux系统下,有一个内置的命令tail
,可以用来输出文件的最后n行。使用该方式只需要在终端中输入上述命令即可。这种方式只适用于Linux系统下。
优点:方便简单,不需要编写任何代码。
缺点:只适用于Linux系统下。
def tail(filename, n):
with open(filename) as f:
# 迭代器函数
def read_last_n_lines():
buffer = ''
data = f.read(4096)
if not data:
return buffer
lines = data.split('\n')
if data[-1] != '\n':
lines.pop()
buffer = ''.join(lines[-n:])
yield buffer
for data in iter(lambda: f.read(4096), b''):
lines = data.split('\n')
if data[-1] != '\n':
buffer = lines.pop()
buffer += ''.join(lines[-n:])
yield buffer
# 将生成器转换为列表并返回
return list(read_last_n_lines())
方法介绍:本方式使用迭代器实现。首先读取一个数据块(大小为4096字节),然后按行分隔,将最后n行保存到内存中。接着将文件指针移动到读取块的开头,同时读取下一个数据块,重复上述步骤,直到读取完整个文件为止。最后,将生成器转换为列表并返回。
优点:可以读取任意大小的文件,适用于读取文本文件和二进制文件。
缺点:代码较为复杂。
读取大文件的最后n行是一个常见的问题。根据不同的需求,可以选择不同的实现方式。方法1适用于读取文本文件,方法2适用于Linux系统下,方法3既适用于读取文本文件,也适用于读取二进制文件。程序员可以根据实际需求选择不同的实现方式。