web-dev-qa-db-ja.com

pythonでファイルの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)

これは各行のCRCを計算しますが、その出力(例:-1767935985)は私が望むものではありません。

Hashlibは私が望むように動作しますが、md5を計算します。

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

zlib.crc32を使用して同様のものを取得することは可能ですか?

22
user203547

もう少しコンパクトで最適化されたコード

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

PS2:コメントでの提案により、古いPSは非推奨になりました(したがって削除されました)。ありがとうございました。私はこれを逃した方法がわかりませんが、本当に良かったです。

27
kobor42

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')
10
Paulo Freitas

整数の下位32ビットを符号なしで8桁の16進数として表示するには、ビットごとに値を「マスク」し、すべて値1の32ビットで構成されるマスクを使用してフォーマットを適用します。つまり:

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

このようにフォーマットしている整数がzlib.crc32からのものか、それとも他の計算からのものかはまったく関係ありません。

5
Alex Martelli

「行」の代わりに固定サイズのチャンクを読み取ることでパフォーマンスが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)

返される文字列に先行ゼロも含まれます。

5
CrouZ

上記の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()
2
sunsys

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

1
Boris

解決:

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 = "")が何であるか本当にわからない...

0
user203547

[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)))
0
bhups