zoukankan      html  css  js  c++  java
  • 借助二分法匹配时间戳实现快速查找日志内容

    前言

      借助二分法能够快速匹配时间戳,根据时间戳来找出需要查找的日志内容。

      查找前提条件:

        1 因为是二分法特性,所以日志的时间必须是按从小到大或者从大到小的顺序排列。

        2 根据查找需要,修改匹配时间戳。

        3 根据不同的时间戳格式,修改对应的代码。

      1 import os
      2 import time
      3 import sys
      4 
      5 class SearchLog(object):
      6 
      7     def __init__(self, file_name='./log.txt'):      
      8         self.fp = open(file_name)             
      9         self.fp.seek(0, os.SEEK_END)      #把指针移动到结尾
     10         self.size = self.fp.tell()       #tell()方法能够告诉我们文件的大小
     11         self.fp.seek(0, os.SEEK_SET)      #吧指针移动到文件内容的开头
     12 
     13     def Search_cmp(self, timestamp, line):      #定义一个匹配时间戳的方法
     14         tmp = line.split(' ')          
     15         riqi=tmp[0]
     16         shijian=tmp[1]
     17         realtime=riqi+' '+shijian                  #在这里可以修改要匹配的时间戳格式
     18         #print realtime
     19         return cmp(timestamp, realtime)          #cmp函数用于比较二者是否相同,如果返回为-1,那么就说明timestamp>realtime,如果等于0,那么两者相等。
     20             
     21             
     22     def Search_LineHead(self):              #定义一个匹配每行开头的方法
     23 
     24         while self.fp.tell() > 0:             
     25             self.fp.seek(-1, os.SEEK_CUR)        #把文件内容的指针在当前位置往前挪一位
     26             val = self.fp.read(1)             # 读取该指针位置的内容
     27             if val == '
    ':                 #匹配该指针内容的值是否等于换行符,等于就跳出循环
     28                 break  
     29             self.fp.seek(-1, os.SEEK_CUR)        #不等于就就继续往前挪一位查找
     30             
     31     def Search_TimeStamp(self, timestamp, start_p = 0):
     32 
     33         fp_start = start_p
     34         fp_end = self.size
     35 
     36         while fp_start < fp_end:              #判断指针开始位置是否小于结束位置
     37             mid = fp_start + (fp_end-fp_start)/2     #找出中间值(利用二分法)
     38             self.fp.seek(mid, os.SEEK_SET)        #通过seek定位到中间值
     39             self.Search_LineHead()            
     40             line = self.fp.readline()
     41             val = self.Search_cmp(timestamp, line)      #调用该方法能够匹配时间戳,返回值为0那么就说明找到了时间戳
     42             if val == 0:          
     43                 print "find timestamp:%s" % line
     44                 return True
     45             elif val == 1:
     46                 fp_start = self.fp.tell()          #如果等于1,说明当前内容的时间戳比输入的时间戳大
     47             else:
     48                 fp_end = mid                  #如果等于其他的,说明当前内容的时间戳比输入的时间戳小,
     49         return False
     50             
     51     def Search_FirstStamp(self, timestamp, start_p = 0):
     52 
     53         first_point = -1
     54         val = self.Search_TimeStamp(timestamp, start_p)
     55 
     56         if val == True:
     57             point = self.fp.tell()                #这里的逻辑是这样的==>
     58             while point > 0:                    #如果search_timestamp这个方法匹配到了时间戳,并且指针恒大于0的话,指针就在当前位置往前挪,直到匹配到换行符,再把这行通过readlie()方法整行独取出来。
     59                 self.fp.seek(-1, os.SEEK_CUR)          #此时再去匹配每行的开头是否等于时间戳,如果等于的话,那么就把指针从文件内容开头移动到匹配到时间戳的这行,标记这行为要查找的时间戳出现的第一行。
     60                 self.Search_LineHead()                  
     61                 point = self.fp.tell()                      
     62                 line = self.fp.readline()
     63                 print line
     64                 if line.startswith(timestamp) == True:
     65                     self.fp.seek(point, os.SEEK_SET)
     66                     continue
     67                 first_point = self.fp.tell()
     68                 break
     69 
     70         return first_point
     71 
     72     def Search_EndStamp(self, timestamp, start_p = 0):
     73 
     74         last_point = -1
     75         val = self.Search_TimeStamp(timestamp, start_p)
     76         if val == True:                        #道理同上,不过这个的就反转过来,用来查找要查找的时间戳的最后一行。
     77             last_point = self.fp.tell()
     78             while last_point < self.size:
     79                 line = self.fp.readline()
     80                 if line.startswith(timestamp) == True:
     81                     last_point = self.fp.tell()
     82                     continue
     83                 print line
     84                 self.fp.seek(last_point, os.SEEK_SET)
     85                 break
     86 
     87             return last_point
     88 
     89     def Search_Dump(self, s_p, e_p):                  #把查找到的内容写入日志
     90         self.fp.seek(s_p, os.SEEK_SET)
     91         f_log=open('search_err.log','wb')
     92         while self.fp.tell() < e_p:
     93             print self.fp.readline()
     94             f_log.write(self.fp.readline())
     95         f_log.close()
     96 
     97     def Search_DeInit(self):
     98         self.fp.close()
     99 
    100 if __name__ == '__main__':
    101     time_s = time.time()
    102     obj = SearchLog(sys.argv[3])
    103     s_point = obj.Search_FirstStamp(sys.argv[1])
    104     if s_point > -1:
    105         e_point = obj.Search_EndStamp(sys.argv[2], s_point)
    106     if s_point > -1:
    107         print s_point , e_point
    108         obj.Search_Dump(s_point, e_point)
    109     else:
    110         print "not find"
    111     print time_s, time.time()
    112 
    113     obj.Search_DeInit()
  • 相关阅读:
    Java中的静态方法
    捕获异常代码
    重载与重写的区别
    继承代码
    Android Studio 快捷键一览
    android两种基本联网方式与一种第三方开源项目的使用
    Android Studio导入github下载的project和module
    SlidingMenu 侧滑菜单的用法
    显示图片的(自定义)吐司Toast
    用volley在Genymotion上获取网页源码
  • 原文地址:https://www.cnblogs.com/liaojiafa/p/5184750.html
Copyright © 2011-2022 走看看