藉助二分法匹配時間戳實現快速查找日誌內容

前言

  藉助二分法可以快速匹配時間戳,根據時間戳來找出須要查找的日誌內容。函數

  查找前提條件:spa

    1 由於是二分法特性,因此日誌的時間必須是按從小到大或者從大到小的順序排列。指針

    2 根據查找須要,修改匹配時間戳。日誌

    3 根據不一樣的時間戳格式,修改對應的代碼。code

  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()
相關文章
相關標籤/搜索