32

ファイルの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ですか?

4

10 に答える 10

33

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

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

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

于 2010-03-05T15:35:38.070 に答える
13

CRC-32 サポートのためのhashlib互換インターフェース:

zlib をインポート

クラス crc32(オブジェクト):
    名前 = 'crc32'
    ダイジェスト サイズ = 4
    ブロックサイズ = 1

    def __init__(self, arg=''):
        self.__digest = 0
        self.update(引数)

    デフコピー(自己):
        copy = super(self.__class__, self).__new__(self.__class__)
        copy.__digest = self.__digest
        コピーを返す

    デフ ダイジェスト (自己):
        self.__digest を返す

    def hexdigest(自己):
        return '{:08x}'.format(self.__digest)

    デフ更新(​​自己、引数):
        self.__digest = zlib.crc32(arg, self.__digest) & 0xffffffff

# これで、hashlib.crc32 = crc32 を定義できます
ハッシュライブラリをインポート
hashlib.crc32 = crc32

# Python > 2.7: hashlib.algorithms += ('crc32',)
# Python > 3.2: hashlib.algorithms_available.add('crc32')
于 2011-02-21T02:59:22.900 に答える
9

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

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

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

于 2009-11-16T15:43:08.120 に答える
3

以下の Altren のソリューションを含めるように編集されました。

forループとファイルバッファリングを使用して、パフォーマンスがわずかに向上した、CrouZの回答の修正されたよりコンパクトなバージョン:

def forLoopCrc(fpath):
    """With for loop and buffer."""
    crc = 0
    with open(fpath, 'rb', 65536) as ins:
        for x in range(int((os.stat(fpath).st_size / 65536)) + 1):
            crc = zlib.crc32(ins.read(65536), crc)
    return '%08X' % (crc & 0xFFFFFFFF)

結果、6700k、HDD で:

(注: 何度も再テストしたところ、一貫して高速でした。)

Warming up the machine...
Finished.

Beginning tests...
File size: 90288KB
Test cycles: 500

With for loop and buffer.
Result 45.24728019630359 

CrouZ solution
Result 45.433838356097894 

kobor42 solution
Result 104.16215688703986 

Altren solution
Result 101.7247863946586  

以下のスクリプトを使用して Python 3.6.4 x64 でテスト済み:

import os, timeit, zlib, random, binascii

def forLoopCrc(fpath):
    """With for loop and buffer."""
    crc = 0
    with open(fpath, 'rb', 65536) as ins:
        for x in range(int((os.stat(fpath).st_size / 65536)) + 1):
            crc = zlib.crc32(ins.read(65536), crc)
    return '%08X' % (crc & 0xFFFFFFFF)

def crc32(fileName):
    """CrouZ solution"""
    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)

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

def crc32altren(filename):
    """Altren solution"""
    buf = open(filename,'rb').read()
    hash = binascii.crc32(buf) & 0xFFFFFFFF
    return "%08X" % hash

fpath = r'D:\test\test.dat'
tests = {forLoopCrc: 'With for loop and buffer.', 
     crc32: 'CrouZ solution', crc: 'kobor42 solution',
         crc32altren: 'Altren solution'}
count = 500

# CPU, HDD warmup
randomItm = [x for x in tests.keys()]
random.shuffle(randomItm)
print('\nWarming up the machine...')
for c in range(count):
    randomItm[0](fpath)
print('Finished.\n')

# Begin test
print('Beginning tests...\nFile size: %dKB\nTest cycles: %d\n' % (
    os.stat(fpath).st_size/1024, count))
for x in tests:
    print(tests[x])
    start_time = timeit.default_timer()
    for c in range(count):
        x(fpath)
    print('Result', timeit.default_timer() - start_time, '\n')

forループはwhileループよりも高速であるため、高速です(ソース: hereおよびhere )。

于 2020-04-25T01:03:12.693 に答える
2

上記の 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()
于 2012-03-16T07:54:27.940 に答える
0

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

于 2009-11-16T15:38:39.843 に答える
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="") が何であるかはよくわかりません...

于 2009-11-16T19:04:34.017 に答える