我正在计算类似于文件的校验和以及我想要移植到python的奇怪协议的麻烦。
校验和是一个4字节的无符号整数,它是添加文件的所有4字节无符号整数的结果。例如,假设以下文件(请注意实际文件大约为16MB):
ff fe fd fc fb fa f9 f8 f7 f6 f5 f4 f3 f2 f1 f0
ef ee ed ec eb ea e9 e8 e7 e6
通过我的实现(见下文),计算如下:
0xfffefdfc + 0xfbfaf9f8 + 0xf7f6f5f4 + 0xf3f2f1f0 + 0xefeeedec + 0xebeae9e8 + 0xe7e60000 = 0x6aba3b7ac
但是,它应该是0xaba3b7ac
我试过这样的事情:
import mmap
import struct
# Prepare file
file = open("file.bin", 'rb')
map = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
# Calculate checksum
checksum = 0
while (map.tell() < map.size()):
checksum += struct.unpack('>I', map.read(4))[0]
print "checksum: ", checksum
# Close file.
map.close()
file.close()
但我发现有两个问题。
0x165c0458b224ae
但它应该类似0xcaac5458
(4字节无符号
整数)。我真的很坚持这一点,所以任何帮助都会非常感激。
提前致谢,抱歉我的英语不好。
更新
Serge Ballesta解决了第一个问题。解决方案是在打印校验和之前添加以下行:
checksum &= 0xffffffff
但计算仍然很慢。我想有一个快速的解决方案,但我不知道该怎么做。
答案 0 :(得分:2)
一种方法是使用array
模块并将所有四个字节加载到内存中,对它们求和,然后强制回到4字节(正如Serge已经提到的那样)。
import os
from array import array
#with open('data.bin', 'wb') as fout:
# fout.write(os.urandom(16800000))
with open('data.bin', 'rb') as fin:
arr = array('L')
arr.fromfile(fin, 16800000 / 4)
arr.byteswap()
checksum = sum(arr) & 0xFFFFFFFF
我的笔记本电脑不到一秒钟......不确定你想要它多快多久......
答案 1 :(得分:1)
我认为你有问题,但不是你描述的问题。
从任意长数字传递到4字节整数就像n4b = n & 0x0FFFFFFFF
我不明白为什么计算为Windows机器编写的C源代码无法在Unix机器上编译。
话虽如此,6293623225328814 & 0xFFFFFFFF
在hexa中提供1488069806
或0x58b224ae
,这不是您预期的结果。我想你有和endianness问题。你应该先用little endian和big endian来计算它,以便知道选择哪个。
# Calculate checksum
checksum_be = 0
checksum_le = 0
while (map.tell() < map.size()):
checksum_be += struct.unpack('>I', map.read(4))[0]
checksum_le += struct.unpack('<I', map.read(4))[0]
checksum_be &= 0x0FFFFFFFF
checksum_le &= 0x0FFFFFFFF
print "checksums: ", checksum_be, checksum_le