在python中计算文件的crc

use*_*547 21 python hash crc

我想计算文件的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)
Run Code Online (Sandbox Code Playgroud)

这计算每行的CRC,但其输出(例如-1767935985)不是我想要的.

Hashlib以我想要的方式工作,但它计算md5:

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

是否可以使用类似的东西zlib.crc32

小智 29

更紧凑和优化的代码

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

PS2:由于评论中的建议,旧PS已弃用 - 因此已删除 - 谢谢.我没有得到,我怎么错过了,但它确实很好.

  • 如果将"prev"设置为0,则不需要担心异常. (2认同)
  • 更快的东西导致相同的输出:def crc(filename):return"%X"%(zlib.crc32(open(filename,"rb").read())&0xFFFFFFFF)这将整个文件读入内存并计算CRC32.当然,文件越大,程序需要的内存越多; 取决于你想要的权衡,内存的速度,或内存的速度. (2认同)

Cro*_*ouZ 14

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)
Run Code Online (Sandbox Code Playgroud)

还包括返回字符串中的前导零。


Pau*_*tas 10

用于CRC-32支持的hashlib兼容接口:

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')


Ale*_*lli 6

要将任何整数的最低32位显示为8个十六进制数字,没有符号,您可以通过位"掩码"该值,并使用由32位组成的掩码全部为1,然后应用格式.即:

>>> x = -1767935985
>>> format(x & 0xFFFFFFFF, '08x')
'969f700f'
Run Code Online (Sandbox Code Playgroud)

因此格式化的整数是来自zlib.crc32还是任何其他计算都是无关紧要的.


Bor*_*ris 5

Python 3.8+(使用海象运算符):

import zlib

def crc32(filename, chunksize=65536):
    """Compute the CRC-32 checksum of the contents of the given filename"""
    with open(filename, "rb") as f:
        checksum = 0
        while (chunk := f.read(chunksize)) :
            checksum = zlib.crc32(chunk, checksum)
        return checksum
Run Code Online (Sandbox Code Playgroud)

chunksize是一次读取文件的字节数。无论您将其设置为什么,您都将获得相同文件的相同哈希值(将其设置得太低可能会使您的代码变慢,太高可能会使用太多内存)。

结果是一个 32 位整数。空文件的 CRC-32 校验和是0.


bhu*_*ups 0

您可以使用 base64 来退出,例如 [ERD45FTR]。并且 zlib.crc32 提供更新选项。

import os, sys
import zlib
import base64

def crc(fileName): fd = open(fileName,"rb") content = fd.readlines() fd.close() prev = None for eachLine in content: if not prev: prev = zlib.crc32(eachLine) else: prev = zlib.crc32(eachLine, prev) return prev

for eachFile in sys.argv[1:]: print base64.b64encode(str(crc(eachFile)))

Run Code Online (Sandbox Code Playgroud)