ファイルの [〜#〜] 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
を使用して同様のものを取得することは可能ですか?
もう少しコンパクトで最適化されたコード
def crc(fileName):
prev = 0
for eachLine in open(fileName,"rb"):
prev = zlib.crc32(eachLine, prev)
return "%X"%(prev & 0xFFFFFFFF)
PS2:コメントでの提案により、古いPSは非推奨になりました(したがって削除されました)。ありがとうございました。私はこれを逃した方法がわかりませんが、本当に良かったです。
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 #これで、hashlib.crc32 = crc32 import hashlib hashlib.crc32 = crc32 #Python > 2.7:hashlib.algorithms + =( 'crc32'、) #Python> 3.2:hashlib.algorithms_available.add( 'crc32')
整数の下位32ビットを符号なしで8桁の16進数として表示するには、ビットごとに値を「マスク」し、すべて値1の32ビットで構成されるマスクを使用してフォーマットを適用します。つまり:
>>> x = -1767935985
>>> format(x & 0xFFFFFFFF, '08x')
'969f700f'
このようにフォーマットしている整数がzlib.crc32
からのものか、それとも他の計算からのものかはまったく関係ありません。
「行」の代わりに固定サイズのチャンクを読み取ることでパフォーマンスが2〜3倍向上したkobor42の回答の修正バージョン:
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)
返される文字列に先行ゼロも含まれます。
上記の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()
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
chunksize
は、ファイルを一度に読み取るバイト数です。何に設定しても、同じファイルに対して同じハッシュが取得されます(設定が低すぎるとコードが遅くなり、高すぎるとメモリが多すぎる可能性があります)。
結果は32ビット整数です。空のファイルのCRC-32チェックサムは0
。
解決:
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 = "")が何であるか本当にわからない...
[ERD45FTR]のように取得するには、base64を使用できます。また、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)))