Python读取文件最末N行,实现Linux的tail命令功能

原文地址:http://shajunxing.tpddns.cn:8888/web/blog/2018-04-17-Python读取文件最末N行,实现Linux的tail命令功能/index.html

思路

主要使用fseek()函数的随机读写能力,从文件末尾按子节反向读取,遇到CR、LF作相应的处理。因为操作系统有缓存优化,所以这种方式的性能应该没问题,另外我看过tail的源代码,用的是lseek()函数,其实和fseek()是一样的。

另外要注意的是,涉及到编码问题,文件的应该用二进制方式读取,每一行读出之后再解码。

代码

def tail(file_name, line_count=10, encoding='utf-8'):
    """
    读取某文本文件最末的行
    :param file_name: 文件名
    :param line_count: 读多少行
    :param encoding: 文件编码
    :return: 数组格式的行列表
    """
    f = open(file_name, mode='rb')
    f.seek(0, io.SEEK_END)
    file_size = f.tell()
    if file_size == 0 or line_count <= 0:
        return []
    lines = []
    prev_char = None
    curr_line = bytearray()
    chars_read = 0
    f.seek(-1, io.SEEK_END)
    while True:
        curr_char = f.read(1)
        chars_read += 1
        # 以下三个步骤:增加字符、增加行、跳出循环,如果文件已经读完,则都要做
        if curr_char not in (b'\n', b'\r') or chars_read == file_size:
            curr_line.extend(curr_char)
        if curr_char == b'\n' or (curr_char == b'\r' and not prev_char == b'\n') or chars_read == file_size:
            curr_line.reverse()
            lines.append(bytes(curr_line).decode(encoding))
            curr_line.clear()
        if len(lines) == line_count or chars_read == file_size:
            break
        # 前退一个字节,此处可以测试一下性能
        f.seek(-2, io.SEEK_CUR)
        prev_char = curr_char
    lines.reverse()
    return lines

你可能感兴趣的:(Python读取文件最末N行,实现Linux的tail命令功能)