我有一个二进制文件,其中某些字段编码为BCD(二进制编码的十进制)。示例如下。
14 75 26 58 87 7F(十六进制格式的原始字节)。
我正在使用(np.void,6)从二进制文件读取和转换,下面是我得到的输出。
b'\ x14 \ x75 \ x26 \ x58 \ x87 \ x7F'
但是我想将输出作为'14752658877',而不使用numpy来填充字符'F'。
下面是代码: 打开(文件名,“ rb”)为f:
while True:
chunk = f.read(chunksize)
if (chunk):
dt = np.dtype([('a','b'), ('b', '>i4'), ('c', 'S15'),('d', np.str, 7),
('e', 'S7'), ('f', np.void, 6)])
x = np.frombuffer (chunk, dtype=dt)
print (x)
else:
break
此外,输入文件包含许多固定长度的二进制记录。什么是使用numpy将其转换并存储为ascii文件的有效方法。
答案 0 :(得分:0)
我不知道numpy是否可以以某种方式加速它,但是可以快速构造一个专门化的函数:
fastDict = {16*(i//10)+(i%10):i for i in range(100)}
def bcdToInteger(bcd):
result = 0
while bcd and bcd[0] in fastDict:
result *= 100
result += fastDict[bcd[0]]
bcd = bcd[1:]
if bcd and bcd[0] & 0xf0 <= 0x90:
result *= 10
result += bcd[0]>>4
if bcd[0] & 0xf <= 9:
result *= 10
result += bcd[0] & 0x0f
return result
>>> print (bcdToInteger(b'\x14\x75\x26\x58\x87\x7F')) # your sequence
14752658877
>>> print (bcdToInteger(b'\x12\x34\xA0')) # first invalid nibble ends
1234
>>> print (bcdToInteger(b'\x00\x00\x99')) # and so does an end of string
99
>>> print (bcdToInteger(b'\x1F')) # a single nibble value
1
只要您继续向其提供有效的BCD字节,它就会将结果乘以100,然后再加上两个新数字。只有最后一个字节需要进一步检查:如果最高半字节有效,那么到目前为止的结果将乘以10,然后将该半字节加起来。如果最低的半字节也有效,则重复此操作。
fastDict
是为了加快速度。这是一个字典,可为00
至99
的所有100个十六进制字节返回正确的值,因此实际计算的数量应尽可能少。您可以不用字典,但这意味着您必须在if
块中为每个字节进行比较和计算。