讓咱們來分析一下這個問題:首先,文件個數很是多,手工查找是不現實的,再說,單憑咱們肉眼,在幾千張圖片或文件裏面找到徹底相同的難度也是很大的。因此要用程序實現。那麼用程序怎麼實現呢?根據什麼判斷兩個文件徹底相同呢?python
一、首先,根據文件名判斷是靠不住的,由於文件名能夠被隨意更改,但文件內容不變。再說在同一個文件夾下面,也不可能出現兩個徹底相同的文件名,操做系統不容許的。算法
二、還有一種方法就是根據文件大小來判斷,這不失爲一種好辦法,可是,文件大小相同的圖片可能不同。再說圖片通常都比較小,超過3M的基本沒有,大部分不夠1M,若是文件夾下面文件特別多,出現大小相同的的文件可能性是至關大的。因此單憑文件大小來比較不靠譜。app
三、還有一種方法是讀取每張圖片的內容,而後比較這個圖片的內容和其餘圖片是否徹底相同,若是內容相同那麼這兩張圖片確定是徹底相同的。這種方法看起來是比較完美的,讓咱們來分析一下他的時空效率:首先每張圖片的內容都要和其餘圖片進行比較,這就是一個二重循環,讀取的效率低,比較的效率更低,全部的都比較下來是很是費時的!內存方面,若是預先把全部圖片讀取到內存能夠加快文件的比較效率,可是普通計算機的內存資源有限,若是圖片很是多,好幾個G的話,都讀到內存是不現實的。若是不把全部的文件讀取到內存,那麼每比較一次以前就要先讀取文件內容,比較幾回就要讀取幾回,從硬盤讀取數據是比較慢的,這樣作顯然不合適。優化
四、那麼有沒有更好的方法呢?我左思右想,絞盡腦汁,最後想到了md5。md5是什麼?你不知道嗎?額,你火星了,抓緊時間duckduckgo吧!也許你會問,md5不是加密的嗎?和咱們的問題有關係嗎?問得好!md5能夠把任意長度的字符串進行加密後造成一個32的字符序列,包括數字和字母(大寫或小寫),由於字符串任何微小的變更都會致使md5序列改變,所以md5能夠看做一個字符串的‘指紋’或者‘信息摘要’,由於md5字符串總共有36的32次方個,因此兩個不一樣的字符串獲得一個相同的md5機率是很小的,幾乎爲0,一樣的道理,咱們能夠獲得每一個文件的md5,若干文件的md5相同的話就基本上能夠確定兩個文件是相同的,由於md5相同而文件不一樣的機率過小了,基本能夠忽略,這樣咱們就能夠這樣作:獲得每一個文件的md5,經過比較md5是否相同咱們就能夠肯定兩張圖片是否相同。下面是代碼實現,python的。加密
# -*- coding: cp936 -*- import md5 import os from time import clock as now def getmd5(filename): file_txt = open(filename,'rb').read() m = md5.new(file_txt) return m.hexdigest() def main(): path = raw_input("path: ") all_md5=[] total_file=0 total_delete=0 start=now() for file in os.listdir(path): total_file += 1; real_path=os.path.join(path,file) if os.path.isfile(real_path) == True: filemd5=getmd5(real_path) if filemd5 in all_md5: total_delete += 1 print '刪除',file else: all_md5.append(filemd5) end = now() time_last = end - start print '文件總數:',total_file print '刪除個數:',total_delete print '耗時:',time_last,'秒' if __name__=='__main__': main()
上面的程序原理很簡單,就是依次讀取每一個文件,計算md5,若是md5在md5列表不存在,就把這個md5加到md5列表裏面去,若是存在的話,咱們就認爲這個md5對應的文件已經出現過,這個圖片就是多餘的,而後咱們就能夠把這個圖片刪除了。下面是程序的運行截圖:spa
咱們能夠看到,在這個文件夾下面有8674個文件,有31個是重複的,找到全部重複文件共耗時155.5秒。效率不算高,能不能進行優化呢?我分析了一下,個人程序裏面有兩個功能比較耗時間,一個是計算每一個文件的md5,這個佔了大部分時間,還有就是在列表中查找md5是否存在,也比較費時間的。從這兩方面入手,咱們能夠進一步優化。操作系統
首先我想的是解決查找問題,或許咱們能夠對列表中的元素先排一下序,而後再去查找,可是列表是變化的,每次都排序的話效率就比較低了。我想的是利用字典進行優化。字典最顯著的特色是一個key對應一個值咱們能夠把md5做爲key,key對應的值就不須要了,在變化的狀況下字典的查找效率比序列效率高,由於序列是無序的,而字典是有序的,查找起來固然更快。這樣咱們只要判斷md5值是否在全部的key中就能夠了。下面是改進後的代碼:code
再看看運行截圖blog
從時間上看,確實比原來快了一點,可是還不理想。下面還要進行優化。還有什麼能夠優化呢?md5!上面的程序,每一個文件都要計算md5,很是費時間,是否是每一個文件都須要計算md5呢?能不能想辦法減小md5的計算次數呢?我想到了一種方法:上面分析時咱們提到,能夠經過比較文件大小的方式來判斷圖片是否徹底相同,速度快,可是這種方法是不許確的,md5是準確的,咱們能不能把二者結合一下?答案是確定的。咱們能夠認定:若是兩個文件徹底相同,那麼這兩個文件的大小和md5必定相同,若是兩個文件的大小不一樣,那麼這兩個文件確定不一樣!這樣的話,咱們只須要先查看文件的大小是否存在在size字典中,若是不存在,就將它加入到size字典中,若是大小存在的話,這說明有至少兩張圖片大小相同,那麼咱們只要計算文件大小相同的文件的md5,若是md5相同,那麼這兩個文件確定徹底同樣,咱們能夠刪除,若是md5不一樣,咱們把它加到列表裏面,避免重複計算md5.具體代碼實現以下:排序
時間效率怎樣呢?看下圖:
只用了7.28秒!比前兩個效率提升了十幾倍!這個時間還能夠接受
算法是個很神奇的東西,不經意間用一下會有意想不到的收穫!上面的代碼還能夠進一步優化,好比改進查找算法等,讀者有啥想法能夠和我交流一下。換成C語言來實現可能會更快。呵呵,我喜歡python的簡潔!
啊啊!快凌晨兩點啦!明天,不,今天還有課呢,悲劇!睡覺去了............
沉睡中。。。。