我是Python的新手,有一些问题。在Python中如何检查两个文件(String和file)是否具有相同的内容?我需要下载一些东西和重命名,但我不想保存相同的东西与两个或多个不同的名称(相同的东西可以在不同的ip地址)。
如果文件很大,我会考虑像这样分段阅读:
compare.py:
import hashlib
teststr = "foo"
filename = "file.txt"
def md5_for_file(f, block_size=2**20):
md5 = hashlib.md5()
while True:
data = f.read(block_size)
if not data:
break
md5.update(data.encode('utf8'))
return md5.digest()
md5 = hashlib.md5()
md5.update((teststr + "n").encode('utf8'))
digest = md5.digest()
f = open(filename, 'r')
print(md5_for_file(f) == digest)
file.txt:
foo
如果字符串和文件匹配
对文件内容使用sha1哈希。
#!/usr/bin/env python
from __future__ import with_statement
from __future__ import print_function
from hashlib import sha1
def shafile(filename):
with open(filename, "rb") as f:
return sha1(f.read()).hexdigest()
if __name__ == '__main__':
import sys
import glob
globber = (filename for arg in sys.argv[1:] for filename in glob.glob(arg))
for filename in globber:
print(filename, shafile(filename))
该程序在命令行上接受通配符,但这只是为了演示目的。
如果您只想要校验和,则不需要使用哈希。Python在binascii模块中有一个校验和。
binascii.crc32(data[, crc])
最好的方法是获取一些哈希值(例如md5)并进行比较。
对下载的每个文件进行散列或校验和。保存这些哈希/校验和的列表。
在将下载的数据保存到磁盘之前,检查列表中是否已经存在哈希/校验和,如果存在,则不保存,如果不存在,则保存文件并将校验和/哈希添加到列表中。
伪代码:
checksums = []
for url in all_urls:
data = download_file(url)
checksum = make_checksum(data)
if checksum not in checksums:
save_to_file(data)
checksums.append(checksum)
虽然哈希和校验和非常适合比较文件列表,但如果您只比较两个特定的文件,并且没有预先计算的哈希/校验和,那么直接比较两个文件要比为每个文件计算哈希/校验和并比较哈希/校验和
快得多def equalsFile(firstFile, secondFile, blocksize=65536):
buf1 = firstFile.read(blocksize)
buf2 = secondFile.read(blocksize)
while len(buf1) > 0:
if buf1!=buf2:
return False
buf1, buf2 = firstFile.read(blocksize), secondFile.read(blocksize)
return True
在我的测试中,在两个50MB的文件上完成64个md5检查需要24.468秒,而64个直接比较只需要4.770秒。此方法还有一个优点,即在发现任何差异时立即返回false,而计算哈希时必须继续读取整个文件。
在不相同的文件上创建早期失败的另一种方法是在使用os.path.getsize(filename)
运行上述测试之前检查它们的大小。当检查具有不同内容的两个文件是否相等时,这种大小差异是非常常见的,因此应该始终是您检查的第一件事。
import os
if os.path.getSize('file1.txt') != os.path.getSize('file2.txt'):
print 'false'
else:
print equalsFile(open('file1.txt', 'rb'), open('file1.txt', 'rb'))