借助二分法匹配时间戳实现快速查找日志内容
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了借助二分法匹配时间戳实现快速查找日志内容相关的知识,希望对你有一定的参考价值。
前言
借助二分法能够快速匹配时间戳,根据时间戳来找出需要查找的日志内容。
查找前提条件:
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 == ‘\n‘: #匹配该指针内容的值是否等于换行符,等于就跳出循环 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()
以上是关于借助二分法匹配时间戳实现快速查找日志内容的主要内容,如果未能解决你的问题,请参考以下文章