11

二进制字段的描述是:

主叫号码,用压缩的BCD码表示,剩余位用“0xF”填充

我尝试使用 struct 格式打印,'16c'我得到:('3', '\x00', '\x02', '\x05', '\x15', '\x13', 'G', 'O', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff')如果我使用'16b'我得到(51, 0, 2, 5, 21, 19, 71, 79, -1, -1, -1, -1, -1, -1, -1, -1). 而且不正确,我应该得到电话号码,上面的号码无效。

print struct.unpack_from('>16b', str(data.read()),offset=46)

以上是无效的代码,我得到无效的数字。我应该用什么格式解压那个 16 字节的字段以及如何转换 BCD 码?

4

2 回答 2

18

BCD 代码使用每个数字 4 位,通常只编码数字 0 - 9。因此序列中的每个字节包含 2 个数字,每 4 位信息 1 个。

以下方法使用生成器来生成这些数字;我假设 0xF 值意味着没有更多的数字可以跟随:

def bcdDigits(chars):
    for char in chars:
        char = ord(char)
        for val in (char >> 4, char & 0xF):
            if val == 0xF:
                return
            yield val

在这里,我使用右移运算符将最左边的 4 位向右移动,并使用按位与来选择最右边的 4 位。

示范:

>>> characters = ('3', '\x00', '\x02', '\x05', '\x15', '\x13', 'G', 'O', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff')
>>> list(bcdDigits(characters))
[3, 3, 0, 0, 0, 2, 0, 5, 1, 5, 1, 3, 4, 7, 4]

该方法适用于c输出;如果直接传递整数,则可以跳过ord方法中的调用(但使用B无符号变体)。或者,您可以直接从文件中读取这 16 个字节,并将此函数直接应用于这些字节,而无需使用 struct.

于 2012-07-26T12:21:09.020 回答
1
a = b'\x12\x34\x5f'

def comp3_to_int(a):
    b = a.hex()
    c = int(b[0:len(b)-1])
    if b[len(b)-1:] == 'd':
        c = -c
    return c
于 2021-03-12T14:34:40.990 回答