Python:如何比较两个二进制文件?

9
在Python中,我需要打印两个二进制文件的差异。我看了一下difflib.Differ,它能做很多事情。
然而difflib假定文本行,所以输出不列出字节索引和十六进制值的差异。
我需要的是输出有哪些字节不同,字节如何不同,两个字节的实际十六进制值。
在Python中,如何比较两个二进制文件(输出:字节差异索引,两个字节的十六进制值)?
我正在做这样的事情:
# /usr/bin/env python2
import difflib
x = open('/path/to/file1', 'r').read()
y = open('/path/to/file2', 'r').read()
print '\n'.join(difflib.Differ().compare(x, y))

但是这个方法并没有输出差异的字节索引。而且它也没有打印十六进制值。

我也可以不使用 difflib。但我觉得应该有一种优雅的解决方案可以使用 difflib - Trevor Boyd Smith
我刚刚查看了man 1 cmp文档,并看到了"逐字节比较两个文件... --verbose输出字节编号和不同的字节值"等信息。我有一种隐隐的感觉,只需从Python中调用cmp命令将是最优雅的解决方案。 - Trevor Boyd Smith
cmp 还涵盖了所有边缘情况(例如一个文件比另一个文件大等)。 - Trevor Boyd Smith
2个回答

0
当difflib进行比较时,它会将每个字符放入一个数组中,并在其前面加上+或-。下面比较了x和y,然后我们来看一下输出结果:
d = difflib.Differ()
e = d.compare(x,y)        #set the compare output to a variable
for i in range(0,len(e)):
    if i.startswith("-"):         #if that char start with "-" is not a match
        print(i + "index is different")

字符以“-”开头表示不匹配。而“+”表示它们是匹配的。

-2

Shell命令cmp已经完全符合我的需求/想法。在Python中重新发明这个功能需要更多的工作/代码/时间...所以我只是从Python中调用了该命令:

#!/usr/bin/env python2
import commands
import numpy as np
def run_cmp(filename1, filename2):
    cmd = 'cmp --verbose %s %s'%(filename1, filename2)
    status, output = commands.getstatusoutput(cmd) # python3 deprecated `commands` module FYI
    status = status if status < 255 else status%255
    if status > 1:
        raise RuntimeError('cmp returned with error (exitcode=%s, '
                'cmd=\"%s\", output=\n\"%s\n\")'%(status, cmd, output))
    elif status == 1:
        is_different = True
    elif status == 0:
        is_different = False
    else:
        raise RuntimeError('invalid exitcode detected')
    return is_different, output
if __name__ == '__main__':
    # create two binary files with different values
    # file 1
    tmp1 = np.arange(10, dtype=np.uint8)
    tmp1.tofile('tmp1')
    # file 2
    tmp2 = np.arange(10, dtype=np.uint8)
    tmp2[5] = 0xFF
    tmp2.tofile('tmp2')
    # compare using the shell command 'cmp'
    is_different, output = run_cmp(filename1='tmp1', filename2='tmp2')
    print 'is_different=%s, output=\n\"\n%s\n\"'%(is_different, output)

在我的系统上,cmp 似乎只返回第一个不匹配的字节,并且我没有看到任何 manpage 选项可以更改它。考虑到我正在试图将大量尝试的 ROM 转储精简为哪些位已经损坏的列表,这使其不合适。 - ssokolow

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