让咱们来分析一下这个问题:首先,文件个数很是多,手工查找是不现实的,再说,单凭咱们肉眼,在几千张图片或文件里面找到彻底相同的难度也是很大的。因此要用程序实现。那么用程序怎么实现呢?根据什么判断两个文件彻底相同呢?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的简洁!
啊啊!快凌晨两点啦!明天,不,今天还有课呢,悲剧!睡觉去了............
沉睡中。。。。