在Python中,检查两个文件是否具有相同的内容。

103

11
我对这个问题的答案感到非常不满意。顶部的答案让人觉得 filecmp.cmp(a, b) 是通过逐字节比较文件的,但实际上它完全不是! 它只是检查缓存的 os.stat() 签名,这对我来说至少导致了错误的结果。只有 filecmp.cmp(a, b, shallow=True) 才会进行真正的逐字节比较。 - xjcl
14
@xjcl 我认为你的意思是shallow=False - kuzzooroo
@kuzzooroo 是的,该死! - xjcl
2个回答

179
是的,如果你需要比较多个文件并存储哈希值以供后续比较,我认为对文件进行哈希处理是最好的方法。由于哈希可能会冲突,根据使用情况可能需要进行逐字节比较。
通常情况下,逐字节比较已经足够高效,而且Python的filecmp模块还可以做其他事情。
请参考链接:http://docs.python.org/library/filecmp.html 例如。
>>> import filecmp
>>> filecmp.cmp('file1.txt', 'file1.txt')
True
>>> filecmp.cmp('file1.txt', 'file2.txt')
False

请注意,默认情况下,filecmp不会比较文件的内容。如果要进行比较,请添加第三个参数shallow=False速度考虑: 通常,如果只需要比较两个文件,通过对它们进行哈希并进行比较会比较慢,而简单的逐字节比较则更高效。例如,下面的代码尝试计时哈希与逐字节比较的速度。
免责声明:这不是计时或比较两种算法的最佳方法,还有改进的空间,但它可以给出一个大致的想法。如果您认为应该改进,请告诉我,我会进行修改。
import random
import string
import hashlib
import time

def getRandText(N):
    return  "".join([random.choice(string.printable) for i in xrange(N)])

N=1000000
randText1 = getRandText(N)
randText2 = getRandText(N)

def cmpHash(text1, text2):
    hash1 = hashlib.md5()
    hash1.update(text1)
    hash1 = hash1.hexdigest()
    
    hash2 = hashlib.md5()
    hash2.update(text2)
    hash2 = hash2.hexdigest()
    
    return  hash1 == hash2

def cmpByteByByte(text1, text2):
    return text1 == text2

for cmpFunc in (cmpHash, cmpByteByByte):
    st = time.time()
    for i in range(10):
        cmpFunc(randText1, randText2)
    print cmpFunc.func_name,time.time()-st

和输出为

cmpHash 0.234999895096
cmpByteByByte 0.0

19
不必做昂贵的哈希运算,使用简单的逐字节比较即可。对于filecmp给予+1赞。 - John Kugelman
20
如果你有很多大文件,没有必要进行昂贵的逐字节比较,可以通过简单的哈希计算来解决。 - Vinko Vrsalovic
4
通常来说,哈希比逐字节比较慢,但由于逐字节比较需要在 Python 循环中进行,所以我认为它会更慢,就像 filecmp 实现的情况一样。 - Anurag Uniyal
5
为了进行一个真实可行的测试,能够展示散列在这种情况下的优势,你需要将一个相同的“文件”与多个不同的文件进行比较,而不仅仅是单一的配对比较。如果我之前表达不太清楚的话:当你需要将一个文件与许多其他文件进行比较时,随着计算哈希值的成本被比较次数所抵消,逐字节比较的速度就会变得更慢(毕竟你需要读取整个文件并进行计算才能得到哈希值)。 - Vinko Vrsalovic
5
默认情况下,filecmp(f1, f2) 是否只比较两个文件的状态而不是它们实际的字节?除非我理解有误,我认为这不是期望的行为。filecmp - Edward Newell
显示剩余8条评论

7
我不确定您是想查找重复文件还是仅比较两个单独的文件。如果是后者,上述方法(filecmp)更好;如果是前者,则以下方法更好。
这里有很多关于重复文件检测的问题。假设它们不是非常小并且性能很重要,您可以:
- 首先比较文件大小,丢弃所有不匹配的文件 - 如果文件大小匹配,则使用您可以处理的最大哈希值进行比较,对文件块进行哈希以避免读取整个大文件
这里有一个带有Python实现的答案(顺便说一句,我更喜欢nosklo的实现)。

如果比较的文件末尾有额外的换行符或空格,即使它们的内容相同,文件大小也可能不同。 - alper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接