createdmd5listcode.py
沒有系統的學習過一門程式設計語言,即使學校學習時也不過聽說過而已。工作之後越發感覺到coding的強大,遂又拾起來開始漫漫學習之路。
朋友推薦學習python,是以就從python開始。
工作上剛好可以提供一些需求,來幫助我确定一個短期的目标,以實作一些工作上的便利為目的,開啟我的python路。
這個筆記是學習了幾天之後,學了很多,但都沒有一個記錄,隻是以文本形式存儲于電腦内,不便于翻閱檢視,偶然想到在學習時翻看的一些幫助部落格,遂也開始用部落格的形式來記錄我的python筆記。
本文是第一篇,開題,當然,也是後期補錄的,代碼是翻閱幫助baidu很多之後慢慢成型的。
需求:給定一個目錄,實作該目錄下所有檔案的md5值。
(工作上有很多資料需要存儲與轉移,是以需要驗證檔案的md5值確定檔案的完整。其實該功能工作上已經給定了一個特定的小工具,但該工具僅僅識别工作特定結構的目錄,沒有普遍性,是以就以實作人和目錄結構下檔案目錄的md5值為功能需求)
想法:
首先是檔案的md5值,這裡用到了hashlib子產品:
import hashlib
### 輸入file完整路徑,傳回其md5值:
def getfilemd5(file):
##判斷輸入是否合法:
if not os.path.isfile(file):
return "請輸入正确的檔案完整路徑!"
##判斷檔案是否太大,太大會造成記憶體過載,直接退出:
elif os.path.getsize(file)>3*(1024**4):
return "輸入的檔案過大,請更換檔案後重試(>3GB)"
####計算合法的檔案md5值:
else:
<pre name="code" class="python"> fileHASHtemp = hashlib.md5()
with open(file,'rb') as md5f:
fileHASHtemp.update(md5f.read())
return fileHASHtemp.hexdigest()
其中最後幾行是實作md5的核心算法(生成md5的方法其實還有,這裡我隻是用到了其中一個):
fileHASHtemp = hashlib.md5()
with open(file,'rb') as md5f:
fileHASHtemp.update(md5f.read())
md5=fileHASHtemp.hexdigest()##md5值
其次是需要周遊整個目錄結構,一下是代碼:
###周遊給出的dir路徑下所有檔案,傳回其檔案數量(個)與總大小(bytes):
def getdirinfo(dir):
##判斷路徑的有效性:
if not os.path.isdir(dir):
return "請輸入正确的完整檔案夾路徑!"
##計算檔案個數與大小:
else:
dirsumsize = 0
dirfilecount = 0
for dirpath,dirnames,filenames in os.walk(dir):
for filename in filenames:
dirfilecount = dirfilecount + 1
dirsumsize = dirsumsize + os.path.getsize(os.path.join(dirpath,filename))
return dirfilecount,dirsumsize
這裡用到了os.path.walk(dir)。
還有就是進度的顯示:
我想到的算法是每計算完一個檔案的md5值,計數就加1,完成md5檔案總大小/總目錄的總大小就是處理進度。
處理速率實作:檔案大小/處理該檔案所使用的時長。
以下是全代碼:
#coding:gbk
import os,os.path
import sys
import hashlib
import time,datetime
### 輸入file完整路徑,傳回其md5值:
def getfilemd5(file):
##判斷輸入是否合法:
if not os.path.isfile(file):
return "請輸入正确的檔案完整路徑!"
##判斷檔案是否太大,太大會造成記憶體過載,直接退出:
elif os.path.getsize(file)>3*(1024**4):
return "輸入的檔案過大,請更換檔案後重試(>3GB)"
####計算合法的檔案md5值:
else:
fileHASHtemp = hashlib.md5()
with open(file,'rb') as md5f:
fileHASHtemp.update(md5f.read())
return fileHASHtemp.hexdigest()
###周遊給出的dir路徑下所有檔案,傳回其檔案數量(個)與總大小(bytes):
def getdirinfo(dir):
##判斷路徑的有效性:
if not os.path.isdir(dir):
return "請輸入正确的完整檔案夾路徑!"
##計算檔案個數與大小:
else:
dirsumsize = 0
dirfilecount = 0
for dirpath,dirnames,filenames in os.walk(dir):
for filename in filenames:
dirfilecount = dirfilecount + 1
dirsumsize = dirsumsize + os.path.getsize(os.path.join(dirpath,filename))
return dirfilecount,dirsumsize
if __name__ == '__main__':
##檢查是否有輸入參數:
if not len(sys.argv)==2:
print "請輸入路徑"
##判斷輸入路徑是否為檔案,是的話就直接輸出該檔案md5值:
elif os.path.isfile(sys.argv[1]):
print ' %s 的md5值:%s' % \
(os.path.split(sys.argv[1])[1] , (getfilemd5(sys.argv[1]).upper()))
##判斷輸入路徑是否為目錄,是的話就周遊目錄,
##并生成各個檔案md5值儲存到目前路徑下的md5list.txt中:
elif os.path.isdir(sys.argv[1]):
gettingmd5count = 0 ##計算md5的個數
for dirpath,dirnames,filenames in os.walk(sys.argv[1]):
for filename in filenames:
filemd5startime = datetime.datetime.now()
##寫md5值到目前檔案夾根目錄:
with open(os.path.join(sys.argv[1],'md5.txt'),'a') as md5valuelist:
md5valuelist.write(os.path.join(dirpath,filename)[21:]+'\t'+\
getfilemd5(os.path.join(dirpath,filename)).upper() + '\t' + \
str(os.path.getsize(os.path.join(dirpath,filename)))+'\n')
filemd5endtime = datetime.datetime.now()
timemd5microseconds = (filemd5endtime-filemd5startime).microseconds/1000000.0
if timemd5microseconds<0.001:
timemd5microseconds = 0.0005
gettingmd5count += 1
filespeed = os.path.getsize(os.path.join(dirpath,filename))/1024.0/1024 \
/ (timemd5microseconds)
##進度顯示:
sys.stdout.write('檢測到%d個檔案,目前正在處理第%d個檔案,處理進度:%.2f%%,速率:%.2fM/s \n' \
% (getdirinfo(sys.argv[1])[0],\
gettingmd5count,\
gettingmd5count*100.0/getdirinfo(sys.argv[1])[0],\
filespeed))
sys.stdout.flush()
問題:
1.處理速率還有問題,表現是顯示可能為0可能會很大很大!
分析原因有:時長的記錄,系統隻能精确到100ms(1000000ms=1s),小檔案可以處理的很快;
如果之前該檔案的md5值計算過,那麼再次計算時感覺處理速度會很快!不知hashlib的具體處理流程。