使用Python Numpy解析包含BCD(二进制编码的十进制)值的二进制文件

时间:2018-11-21 09:28:01

标签: python numpy

我有一个二进制文件,其中某些字段编码为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文件的有效方法。

1 个答案:

答案 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是为了加快速度。这是一个字典,可为0099的所有100个十六进制字节返回正确的值,因此实际计算的数量应尽可能少。您可以不用字典,但这意味着您必须在if块中为每个字节进行比较和计算。