使用缓冲区在 Python 中计算二进制文件的 CRC / CRC32 哈希 / 校验和

6

我一直在尝试自学Python,所以不是很理解我在做什么。很不好意思,但我的问题应该很容易回答。我想用类似于这样的代码在二进制文件上执行CRC校验和:

# http://upload.wikimedia.org/wikipedia/commons/7/72/Pleiades_Spitzer_big.jpg

import zlib

buffersize = 65536

with open('Pleiades_Spitzer_big.jpg', 'rb') as afile:
    buffr = afile.read(buffersize)
    while len(buffr) > 0:
        crcvalue = zlib.crc32(buffr)
        buffr = afile.read(buffersize)

print(format(crcvalue & 0xFFFFFFFF, '08x'))

正确的结果应该是"a509ae4b",但我的代码结果是"dedf5161"。我认为问题出在校验和是在文件的第一个或最后64kb上计算而不是整个文件上计算。如何修改代码以检查整个文件而不将整个文件加载到内存中?目前代码在Python 2.x或3.x中都可以“工作”。如果必须选择其中之一,我更喜欢使用3.x版本的Python。
2个回答

12

你当前只计算了文件的最后一块的CRC。为了解决这个问题,请将当前的传递给crc32作为起始值:

import zlib

buffersize = 65536

with open('Pleiades_Spitzer_big.jpg', 'rb') as afile:
    buffr = afile.read(buffersize)
    crcvalue = 0
    while len(buffr) > 0:
        crcvalue = zlib.crc32(buffr, crcvalue)
        buffr = afile.read(buffersize)

print(format(crcvalue & 0xFFFFFFFF, '08x')) # a509ae4b

以下是Python文档中相关的部分:

如果提供了value,它将用作校验和的起始值;否则使用默认值0。传递value允许在多个输入的连接上计算运行校验和。


我读过Python文档,但没有理解得足够好,以至于无法使代码运作。非常感谢! - Dave Brunker

1

虽然被@niemmi接受的答案非常出色和准确,但这里提供一个兼容Python 3.8+的解决方案,可以帮助简化代码。


Python 3.8+

下面的示例使用海象赋值运算符:=)来跟踪正在读取的块:

import zlib

size = 1024*1024*10  # 10 MiB chunks
with open('/tmp/test.txt', 'rb') as f:
    crcval = 0
    while chunk := f.read(size):
        crcval = zlib.crc32(chunk, crcval)

print(f'{crcval & 0xFFFFFFFF:08x}')

测试

echo "Some boring example text in a file." > /tmp/test.txt

$ crc32 /tmp/test.txt
2a30366b

使用上面的示例代码计算出的校验和值为:
2a30e66b

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