自己编写代码,删除计算机中的相同文档
不要整天在脑壳里安装优化算法,要及时取出优化算法,应用到实际设计中!
这几天闲着没事在百度上淘了一些图片,很少,可能只有几万元,其中有很多美女照片奥!嘿嘿!暂且不说照片是怎么拥有的,我们来谈谈获得照片后发生的事情。
第一个问题是有些照片没有文件后缀名。在windows下,没有文件后缀名的文件无法正确识别,没有预览,打开后要选择打开,费力!这种情况很容易处理,只需将文件后缀名添加到每张照片中即可。没有文件后缀名的照片不多,不到1000张。一个个改太麻烦了。幸运的是,我学习了it。早上写了一个程序流程,批量修改http。://www.cnblogs.com/ma6174/archive/2012/05/04/2482378.html。即使克服了这种情况。下面又遇到了一个新的问题:照片多了,难免会重复。有些照片完全一样,没必要全部保存,所以我想删除我所有的重复图片。
让我们分析一下这种情况:首先,有大量的文档,不可能手工搜索。此外,仅仅依靠每个人的眼睛,在成千上万的照片中找到完全相同的难度系数也是非常大的。如果不是图片而是其他文本文档,在不能浏览的情况下很难区分。所以要使用程序代码。那么如何实现程序流程呢?在什么基础上区分两个文档完全一致?首先,根据文件夹的名称判断不可靠,因为文件夹的名称可以随意更改,但文件信息不会更改。此外,在同一个文件夹下,不可能有两个完全相同的文件夹名称,禁止计算机操作系统。还有一种方法可以根据图片的大小来确定,这是一种很好的方法,但相同大小的图片可能会有所不同。此外,照片通常相对较小,几乎没有超过3M的照片,绝大多数不到1M。如果文件夹名称下有很多文档,则相同大小的文档的可能性相当大。因此,仅凭图片大小进行比较是不可靠的。另一种方法是将每张照片的内容输入到哪里,然后比较这张图片的具体内容。其他图片是否完全一致。如果内容相同,这两张图片必须完全相同。这种方法看起来很完美。让我们分析一下它的时间效率:首先,每张照片的内容都应该与其他图片进行比较。这是一个二重循环系统。输入效率低,效率低。它需要很多时间来比较它!在操作内存层面,如果提前将所有图片输入操作内存,可以加速文档的比较和效率,但一般计算机的内存资源有限。如果有很多图片,很多G,就不太可能学习操作内存。如果你不把你的文件读取到运行记忆中,你应该在每次比较之前读取文件的具体内容。如果你比较几次,你需要加载几次。从硬盘上读取信息很慢。这显然是个问题。有没有更好的方法?我想了想,煞费苦心,终于想起了md5。md5是啥?你不知道吗?嗯,你火花了,尽快duckgo吧!也许你会问,md5不是加密的吗?和我们的问题有关吗?问得好!md5可以加密任意长度的字符串,形成32个字符序列,包括字母数字(英文大写或小写字母)。由于字符串数组的所有细微变化都会导致md5序列的变化,md5可以理解为字符串数组的“指纹识别”或“信息内容介绍”,因为md5字符串数组共有3632个,因此,两个不同的字符串数组不太可能得到相同的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对应的文档已经出现了。这张图是多余的,然后我们可以删除这张图。以下是程序流程的操作截图:
你可以看到,在这样一个文件夹的名称下有8674个文件,31个文件是重复的,需要155.5秒才能找到所有重复的文件。以下是程序流程的操作截图:
你可以看到,在这样一个文件夹的名称下有8674个文档,31个是重复的,需要155.5秒才能找到所有的重复文件。效率不是很高,可以改进吗?我分析了一下。我的程序中有两个数据需要时间。一是计算每个文件信息md5,占绝大多数。此外,在页面上搜索md5是否存在需要时间。我们可以从两个方面进一步优化。
我首先想到的是处理正确的问题。也许我们可以先删除列表中的原始元素,然后搜索它们,但目录已经改变了。如果每次都安排,效率相对较低。我想的是用词典来改进。词典最显著的特点是,key对应的值也可以以md5作为key,key对应的值不能使用。在变化的情况下,词典的搜索速度高于编码序列。由于编码序列无序,词典规范有序,搜索自然快速。所以我们只需要区分md5值是否在所有key中。以下是改进后的编码:
# -*- 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.keys():
total_delete = 1
print '删掉',file
else:
all_md5[filemd5]=
end = now()
time_last = end - start
print 删除数量:total_delete
print 用时:time_last,'秒'if __name__=='_____main__':
main()
看看操作截屏
从这个时候来看,真的比以前快了一点,但还是不理想。下面还需要改进。下面还需要改进。有什么可以优化的吗?md5!对于上述程序流程,每个文档都需要计算md5,这是非常耗时的。每个文档都需要计算md5吗?MD5计算频率能尽可能降低吗?我想到了一种方法:在上面的分析中,我们提到我们可以通过比较图片的大小来区分照片是否完全一致,速度是否更快,但这种方法是不准确的,md5是准确的,可以结合两者吗?合一下?当然可以。您可以确定,如果两个文档完全一致,那么两个文档的大小必须与md5相同,如果两个文档的信息大小不同,那么这两个文档无疑是不同的!在这种情况下,我们只需要检查文件的大小是否存在于size词典中。如果没有,我们将参与size词典。如果有大小,说明至少有两张图片大小相同。然后我们只需要计算图片大小相同的文件信息md5。如果md5相同,那么这两个文档无疑是完全相同的。我们可以删除它们。如果md5不同,请将其添加到目录中,防止重复计算md5。实际代码编写如下:
# -*- 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 = {}
all_size = {}
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:
size = os.stat(real_path).st_size
name_and_md5=[real_path,'']
if size in all_size.keys():
new_md5 = getmd5(real_path)
if all_size[size][1]=‘=’:
all_size[size][1]=getmd5(all_size[size][0])
if new_md5 in all_size[size]:
print '删除',file
total_delete = 1
else:
all_size[size].append(new_md5)
else:
all_size[size]=name_and_md5
end = now()
time_last = end - start
print “删除数量:total_delete
print 用时:time_last,'秒'if __name__=='_____main__':
main()
时间效率是多少?见下图:
只用了7.28秒!见下图: 只用了7.28秒!比第四效率高十倍以上!这个时候也可以接受算法是一件非常美妙的事情,不知不觉中会有不同的收获!上面的代码可以进一步优化,比如改进搜索算法。读者可以和我交流他们的看法。C语言很可能更容易实现。呵呵,我很喜欢python的简约!啊啊啊!凌晨三点!明天,不,今天也有课,不幸!睡觉了...