вычислить crc файла в python - PullRequest
20 голосов
/ 16 ноября 2009

Я хочу вычислить 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?

Ответы [ 6 ]

27 голосов
/ 05 марта 2010

Чуть более компактный и оптимизированный код

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

PS2: старый PS устарел - поэтому удален - из-за предложения в комментарии. Спасибо. Я не понимаю, как я это пропустил, но это было действительно хорошо.

10 голосов
/ 21 февраля 2011

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')
6 голосов
/ 16 ноября 2009

Чтобы отобразить младшие 32 бита любого целого числа в виде 8 шестнадцатеричных цифр, без знака, вы можете «замаскировать» значение, используя бит, и добавив в него маску, состоящую из 32 бит, со значением 1, затем примените форматирование. I.e.:

>>> x = -1767935985
>>> format(x & 0xFFFFFFFF, '08x')
'969f700f'

Совершенно неважно, является ли целое число, которое вы таким образом форматируете, взято из zlib.crc32 или любого другого вычисления.

3 голосов
/ 16 марта 2012

Объедините вышеуказанные 2 кода, как показано ниже:

try:
    fd = open(decompressedFile,"rb")
except IOError:
    logging.error("Unable to open the file in readmode:" + decompressedFile)
    return 4
eachLine = fd.readline()
prev = 0
while eachLine:
    prev = zlib.crc32(eachLine, prev)
    eachLine = fd.readline()
fd.close()
1 голос
/ 16 ноября 2009

Вы можете использовать base64 для выхода как [ERD45FTR]. И zlib.crc32 предоставляет опции обновления.

<code>import os, sys
import zlib
import base64</p>

<p>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</p>

<p>for eachFile in sys.argv[1:]:
  print base64.b64encode(str(crc(eachFile)))
0 голосов
/ 16 ноября 2009

решение:

import os, sys
import zlib

def crc(fileName, excludeLine="", includeLine=""):
  try:
        fd = open(fileName,"rb")
  except IOError:
        print "Unable to open the file in readmode:", filename
        return
  eachLine = fd.readline()
  prev = None
  while eachLine:
      if excludeLine and eachLine.startswith(excludeLine):
            continue   
      if not prev:
        prev = zlib.crc32(eachLine)
      else:
        prev = zlib.crc32(eachLine, prev)
      eachLine = fd.readline()
  fd.close()    
  return format(prev & 0xFFFFFFFF, '08x') #returns 8 digits crc

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

не знаю, что это такое (excludeLine = "", includeLine = "") ...

...