在Python中计算文件的CRC

35 投票
10 回答
56973 浏览
提问于 2025-04-15 16:04

我想计算一个文件的 CRC 值,想要的输出格式是像 E45A12AC 这样的结果。以下是我的代码:

#!/usr/bin/env python 
import os, sys
import zlib

def crc(fileName):
    fd = open(fileName,"rb")
    content = fd.readlines()
    fd.close()
    for eachLine in content:
        zlib.crc32(eachLine)

for eachFile in sys.argv[1:]:
    crc(eachFile)

这段代码是计算每一行的 CRC 值,但输出的结果(比如 -1767935985)并不是我想要的。

虽然 Hashlib 可以满足我的需求,但它计算的是 md5 值:

import hashlib
m = hashlib.md5()
for line in open('data.txt', 'rb'):
    m.update(line)
print m.hexdigest()

请问使用 zlib.crc32 是否可以得到类似的结果呢?

10 个回答

15

这是一个与 hashlib 兼容的接口,用于支持 CRC-32 的功能:

import zlib

class crc32(object):
    name = 'crc32'
    digest_size = 4
    block_size = 1

    def __init__(self, arg=''):
        self.__digest = 0
        self.update(arg)

    def copy(self):
        copy = super(self.__class__, self).__new__(self.__class__)
        copy.__digest = self.__digest
        return copy

    def digest(self):
        return self.__digest

    def hexdigest(self):
        return '{:08x}'.format(self.__digest)

    def update(self, arg):
        self.__digest = zlib.crc32(arg, self.__digest) & 0xffffffff

# Now you can define hashlib.crc32 = crc32
import hashlib
hashlib.crc32 = crc32

# Python > 2.7: hashlib.algorithms += ('crc32',)
# Python > 3.2: hashlib.algorithms_available.add('crc32')
22

这是对kobor42回答的一个改进版本,通过读取固定大小的块而不是逐行读取,性能提高了2到3倍:

import zlib

def crc32(fileName):
    with open(fileName, 'rb') as fh:
        hash = 0
        while True:
            s = fh.read(65536)
            if not s:
                break
            hash = zlib.crc32(s, hash)
        return "%08X" % (hash & 0xFFFFFFFF)

这个改进还在返回的字符串中包含了前导零。

35

这段代码更简洁和优化了一些

def crc(fileName):
    prev = 0
    for eachLine in open(fileName,"rb"):
        prev = zlib.crc32(eachLine, prev)
    return "%X"%(prev & 0xFFFFFFFF)

PS2:旧的PS已经不再使用了,所以删除了,感谢评论中的建议。我不知道我怎么会错过这个,但确实很不错。

撰写回答