📜  实现自己的尾巴(读取大文件的最后n行)(1)

📅  最后修改于: 2023-12-03 14:53:37.057000             🧑  作者: Mango

实现自己的尾巴——读取大文件的最后n行

在编写程序时,我们有时需要处理很大的文件。然而,直接读取整个文件可能会导致内存不足的问题。在这种情况下,只需要读取文件的最后几行,就可以解决问题了。本文将介绍几种实现方式,帮助程序员解决读取大文件的最后n行的问题。

方法1:使用文件指针
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行。如果行末有换行符,则需要去除。这种方式适用于读取文本文件,但是对于二进制文件则需要进行手动处理。

  • 优点:代码简单,适用于读取文本文件。

  • 缺点:不适用于读取二进制文件。

方法2:使用脚本命令
tail -n 10 filename
  • 方法介绍:在Linux系统下,有一个内置的命令tail,可以用来输出文件的最后n行。使用该方式只需要在终端中输入上述命令即可。这种方式只适用于Linux系统下。

  • 优点:方便简单,不需要编写任何代码。

  • 缺点:只适用于Linux系统下。

方法3:使用迭代器
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既适用于读取文本文件,也适用于读取二进制文件。程序员可以根据实际需求选择不同的实现方式。