Python:基於MD5的文件監聽程序

前述

  寫了一個基於MD5算法的文件監聽程序,經過不一樣的文件可以生成不一樣的哈希函數,來實現實現判斷文件夾中的文件的增長、修改、刪除和過濾含有特定字符的文件名的文件。html

 

需求說明

  須要實現對一個文件夾下的文件的增長、修改和刪除的監控, 一旦發生上述操做,則進行提示。能夠選擇過濾掉文件名中的特定字符和只監聽文件名中含有特定字符的文件。python

  

簡述

  •  首先,關於文件的增長、修改、刪除的反饋,能夠想到利用MD5等相似的加密算法,由於文件自己能夠生成哈希值,只要文件內容或者文件名被修改過,就會生成和修改以前的哈希值不一樣的值,所以能夠利用dict來存儲,一個文件名對應一個哈希值來存儲。其中增長和刪除就對應一個新增長的鍵值對和一個減小的鍵值對,而修改則能夠理解爲刪除了舊的文件、增長了一個新的文件。

   MD5算法能夠直接利用第三方的 hashlib 庫來實現git

1 m = hashlib.md5()
2 myFile = open(full_path, 'rb')
3     for line in myFile.readlines(): #以行爲單位不斷更新哈希值,避免文件過大致使一次產生大量開銷
4            m.update(line)   #最後能夠獲得整個文件的哈希值

 

  • 第二,關於濾掉文件名中的特定字符和只監聽文件名中含有特定字符的文件的功能,這個其實很是簡單,只須要用 list 分別對須要過濾和必須存在字符串進行存儲, 而後利用標誌位和字符串的子串包含性進行判斷就能夠了,只有知足條件的文件能夠產生哈希值,產生哈希值也就意味着被監聽了。

   判斷字符串中是否含有字串最經常使用的方法是 in 和 string 中的 find 方法,這裏就再也不贅述,能夠直接看下面的代碼github

 

  • 第三,由於要同時監控多個文件夾,因此必需要利用到線程來處理,建立一個線程池來存儲線程, 線程利用了 threading 庫,而且實現一個線程類來處理線程的操做
class myListener(threading.Thread):
1 thread1 = myListener(mydir, json_list_include, json_list_exclude)   #生成線程

 

說明

  須要額外說明的一點是,在傳輸須要監聽的文件夾、必須包含的字段以及過濾字段的時候,我這裏是利用配置文件的形式來存儲的。說到底,是利用 toml 格式的數據進行的傳輸,toml格式和 json格式相比,用戶的可讀性更強一些,爲了便於博客展現,所以利用了 toml 格式算法

  首先利用代碼生成了一下toml格式的文件,之後再想用的話,程序打包以後,能夠直接修改配置文件來實現對程序的控制。json

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author: JYRoooy
 4 import collections
 5 import json 6 import toml 7 if __name__ == '__main__': 8 myOrderDict = collections.OrderedDict 9 myOrderDict = {'dict':[{'path':'E:/testing', 'include':['log_'], 'exclude': ['.swp', '.swx', 'tmp']},{'path':'E:/tmp', 'include':['.record'], 'exclude': ['.tmp']}]} 10 myToml = toml.dump(myOrderDict, open('E:/python/code/PythonProject/tomlConfig.txt','w+'))

  

  toml文件多線程

  格式說明, 一個 dict 對應一個監聽的文件夾和須要 過濾(exculde) 和 含有(include) 的字段,解釋一下,這裏的字段只是文件名的字段,監控 E:/testing 目錄下的文件,要包含 log_ 字段的文件,且不包含 .swp .swx .tmp 字段的文件, 而且監控 E:/tmp 目錄下的文件,要包含 .record 字段的文件,且不包含 .tmp 的文件。app

 

代碼

完整程序的代碼,具體解釋能夠看註釋函數

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author: JYRoooy
 4 import toml
 5 import hashlib
 6 import os
 7 import sys
 8 import time
 9 import importlib
10 import threading
11 importlib.reload(sys)
12 
13 class myListener(threading.Thread):
14     '''
15     監聽類
16     '''
17     def __init__(self, input_dir, filt_in, filt_ex):  #文件夾路徑,必須包含的字符,必須過濾的字符
18         threading.Thread.__init__(self)
19         self.input_dir = input_dir
20         self.filt_in = filt_in
21         self.filt_ex = filt_ex
22         self.dict = {}     #用來存儲文件名和對應的哈希值
23         self.file_list = []   #存儲每一次掃描時的文件的文件名
24         self.pop_list = []   #存儲須要刪除的文件名
25 
26     def run(self):
27         while (1):   #保證文件夾一直處於被監聽的狀態
28             for cur_dir, dirs, files in os.walk(self.input_dir):
29                 if files != []:
30                     self.file_list = []
31                     for each_file_1 in files:
32                         each_file = each_file_1
33                         if self.filt_in:       #判斷文件名中是否有必須存在的字段
34                             flagone = 0
35                             for i in range(len(self.filt_in)):
36                                 if self.filt_in[i] in each_file:
37                                     flagone += 1
38                             if flagone == 0:
39                                 continue
40 
41                         if self.filt_ex:       #判斷文件名中是否有必須過濾掉的字段
42                             flagtwo = 0
43                             for i in range(len(self.filt_ex)):
44                                 if self.filt_ex[i] in each_file:
45                                     flagtwo = 1
46                             if flagtwo==1:
47                                 continue
48 
49                         self.file_list.append(each_file)
50                         full_path = os.path.join(cur_dir, each_file)
51                         m = hashlib.md5()   #實例化md5算法
52 
53                         myFile = open(full_path, 'rb')
54 
55                         for line in myFile.readlines():
56                             m.update(line)
57                         if each_file not in self.dict.keys():     #若是當前的dict中沒有這個文件,那麼就添加進去
58                             self.dict[each_file] = m.hexdigest()   #生成哈希值
59                             print('文件夾:' +cur_dir+ "中的文件名爲:" + each_file + "的文件爲新文件" + time.strftime('%Y-%m-%d %H:%M:%S',
60                                                                                   time.localtime(time.time())))
61                         if each_file in self.dict.keys() and self.dict[each_file] != m.hexdigest():      #若是當前dict中有這個文件,可是哈希值不一樣,說明文件被修改過,則須要對字典進行更新
62                             print('文件夾:' +cur_dir+ "中的文件名爲:" + each_file + "的文件被修改於" + time.strftime('%Y-%m-%d %H:%M:%S',
63                                                                                   time.localtime(time.time())))
64                             self.dict[each_file] = m.hexdigest()
65                         myFile.close()
66                 pop_list = []
67                 for i in self.dict.keys():
68                     if i not in self.file_list:    #當字典中有不在當前文件名列表中時,說明文件已經被刪除
69                         print('文件夾:' +cur_dir+ '中的文件名爲:' + i + "的文件已被刪除!!!" + time.strftime('%Y-%m-%d %H:%M:%S',
70                                                                          time.localtime(time.time())))
71                         pop_list.append(i)
72                 for i in pop_list:
73                     self.dict.pop(i)
74 
75             time.sleep(2)
76 
77 if __name__ == '__main__':
78     threads = []    #用來存儲線程的線程池
79     with open('E:/python/code/PythonProject/tomlConfig.txt','r+') as f:    #讀取toml格式的文件,並分解格式
80         mytoml = toml.load(f)
81         myList = mytoml['dict']
82         for i in range(len(myList)):     #由於可能同時須要監聽多個文件夾,因此利用線程池處理多線程
83             json_list_include = []
84             json_list_exclude = []
85             mydir = myList[i]['path']
86             for sublist in range(len(myList[i]['include'])):
87                 json_list_include.append(myList[i]['include'][sublist])
88             for sublist in range(len(myList[i]['exclude'])):
89                 json_list_exclude.append(myList[i]['exclude'][sublist])
90             thread1 = myListener(mydir, json_list_include, json_list_exclude)   #生成線程
91             threads.append(thread1)
92 
93         for t in threads:    #開啓全部線程
94             t.start();

 

運行結果

  兩個文件夾中的文件加密

  

 

 

  第一次運行程序, 能夠看到已經按照過濾規則完成了過濾和監聽

  修改 loko.record 文件爲 loko.re,再來看結果

  能夠看到已經完成了監聽,由於 loko.re 文件,並符合監聽的規則,因此不作出監聽,而咱們前面說過,一個修改至關於一個刪除和一個新建操做,因此監聽程序提示原文件被刪除了

 

寫在後面

  其餘的效果我就不一一展現了。

  程序也沒有實現很複雜的效果,代碼已經上傳 github -- https://github.com/JYRoy/MyFileListener

  已經更新了Java版本的代碼 https://www.cnblogs.com/jyroy/p/10575190.html

  歡迎大佬們交流~

相關文章
相關標籤/搜索