zoukankan      html  css  js  c++  java
  • 实现类似tail -f file功能

    python版本py3

    tail -f file是打印最后10行,然后跟踪文件追加的内容打印出来。

    python3 以为本方式打开的话,不能回退(f.seek(-1,1)),所有以'rb'方式打开文件。

    思路是f.seek(-n,2)从文件末尾回退n字节,然后f.readlines()读取文件,如果读到的少于10行,则再往前移动n字节,直到读到11行,然后打印出来,再跟踪打印文件追加的内容,并打印。

    知识点:

    f.tell()返回当前的文件位置

    f.seek(n,m),m=0从文件开头往前或往后移到n字节,负数表示像文件头方向移动,正数表示向文件尾移动,m=1表示从文件指针当前位置移动,m=2表示从文件末尾开始移动,指针超出边界会报错。

    f.seek(0,2)移到文件末尾

    open(file,'r')以文本方式打开,open(file,'rb')以二进制方式打开。

    由于文档是utf8或gbk编码保存的文件,以二进制方式打开文件读取到的是uft8或gbk编码(字节),所有打印是需要解码。

    个人觉得在py2中,

    "我”是str类型,utf8或gbk编码保存在内存中,只能进行解码成unicode操作:

    py3中

    ‘我’是str类型,以unicode编码放在内存中,只能解码成bytes操作:

    具体代码实现:

     1 #! -*- coding:utf-8 -*-
     2 # runing on python3
     3 import os,sys
     4 from time import sleep
     5 COUDING=sys.getfilesystemencoding()
     6 
     7 class tail(object):
     8 
     9     def __init__(self,n,filename,callback):
    10         self._n = n
    11         self.filename= filename
    12         self.callback = callback
    13         self.track()
    14 
    15     def track(self):
    16         if os.path.exists(self.filename):
    17             if os.path.isfile(self.filename):
    18                 try:
    19                     with open(self.filename,'rb') as f:
    20                         self._file = f
    21                         # 文件内部指针移到末尾
    22                         f.seek(0, os.SEEK_END)
    23                         self._len = f.tell()
    24                         self.showline()
    25                         while True:
    26                             line = f.readline()
    27                             self.callback(line)
    28                             sleep(0.5)
    29                 except Exception as e:
    30                     print(e)
    31             else:
    32                 sys.stdout.write("tail: %s: cannot follow end of this type of file; giving up on this name"%self.filename)
    33         else:
    34             sys.stdout.write("tail: cannot open `%s' for reading: No such file or directory"%self.filename)
    35 
    36     def showline(self):
    37         # 假设每行100个字节
    38         line_len = 100
    39         n = self._n
    40         # 文件字节数小于500,直接从头读文件,然后取后5行
    41         if self._len < n * line_len:
    42             self._file.seek(0)
    43             lines = self._file.readlines()[-self._n:]
    44             self.callback(lines)
    45         else:
    46             # 指针总文件末尾往文件头移动n * line-len个字节
    47             while True:
    48                 self._file.seek(-n*line_len,os.SEEK_END)
    49                 lines = self._file.readlines()
    50                 # 读n+1行,因为seek是以字节为单位移到的,如果移到一个中文字符的编码的中间,会出现UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
    51                 if len(lines) > self._n:
    52                     self.callback(lines[-self._n:])
    53                     return
    54                 else:
    55                     n += 1
    56 
    57 def printline(lines):
    58     if isinstance(lines,list):
    59         for line in lines:
    60             sys.stdout.write(line.decode(COUDING))
    61     elif isinstance(lines,bytes):
    62         sys.stdout.write(lines.decode(COUDING))
    63 
    64 if __name__ == "__main__":
    65     if len(sys.argv) < 2:
    66         print("xxx")
    67     else:
    68         # 可加参数解析模块来获取文件名和显示最后多少行
    69         tail(10,sys.argv[1],printline)
  • 相关阅读:
    项目管理和项目群管理的区别
    项目群管理
    PRINCE2如何完善PMBOK和您的PMP资格证书?
    为什么需要prince2项目管理方法论?
    PMP和PRINCE2到底有什么区别?哪个含金量更高?
    同步和异步
    Promise理解
    async和await实现异步的同步等待
    Mysql数据库操作基础步骤
    PHP和javascript区别
  • 原文地址:https://www.cnblogs.com/owasp/p/6407309.html
Copyright © 2011-2022 走看看