Вычислить crc файла в python
Я хочу вычислить 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
?
Ответы
Ответ 1
Немного более компактный и оптимизированный код
def crc(fileName):
prev = 0
for eachLine in open(fileName,"rb"):
prev = zlib.crc32(eachLine, prev)
return "%X"%(prev & 0xFFFFFFFF)
PS2: Старый PS устарел - поэтому удален - из-за предложения в комментарии. Спасибо. Я не понимаю, как я пропустил это, но это было действительно хорошо.
Ответ 2
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')
Ответ 3
Чтобы показать любое целое число наименьших 32 битов в виде 8 шестнадцатеричных цифр без знака, вы можете "замаскировать" значение по биту и создать его с помощью маски из 32 бит со значением 1, а затем применить форматирование. То есть:.
>>> x = -1767935985
>>> format(x & 0xFFFFFFFF, '08x')
'969f700f'
Не имеет значения, является ли целое число, которое вы таким образом форматируете, из zlib.crc32
или любых других вычислений вообще.
Ответ 4
Объедините вышеуказанные 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()
Ответ 5
Вы можете использовать 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)))
Ответ 6
решение:
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 =" ")...
Ответ 7
Модифицированная версия ответа kobor42, с производительностью, улучшенной в 2-3 раза за счет чтения фрагментов фиксированного размера вместо "строк":
def crc32(fileName):
fh = open(fileName, 'rb')
hash = 0
while True:
s = fh.read(65536)
if not s:
break
hash = zlib.crc32(s, hash)
fh.close()
return "%08X" % (hash & 0xFFFFFFFF)
Также включает ведущие нули в возвращаемой строке.