打包成c类型,并获得二进制值



我使用下面的代码将一个整数打包成unsigned short,如下所示,

raw_data = 40
# Pack into little endian
data_packed = struct.pack('<H', raw_data)

现在我试着像下面这样解包结果。我使用utf-16-le,因为数据被编码为little-endian。

def get_bin_str(data):
bin_asc = binascii.hexlify(data)
result = bin(int(bin_asc.decode("utf-16-le"), 16))
trimmed_res = result[2:]
return trimmed_res
print(get_bin_str(data_packed))

不幸的是,它抛出以下错误,

result = bin(int(bin_asc.decode("utf-16-le", 16)) ValueError:无效以16为基数的int(): '㠲~ '

我如何正确解码字节在小端二进制数据正确?

使用unpack来反转您打包的东西。数据不是UTF编码的,所以没有理由使用UTF编码。

>>> import struct
>>> data_packed = struct.pack('<H', 40)
>>> data_packed.hex()   # the two little-endian bytes are 0x28 (40) and 0x00 (0)
2800
>>> data = struct.unpack('<H',data_packed)
>>> data
(40,)

unpack返回一个元组,因此对其进行索引以获得单个值

>>> data = struct.unpack('<H',data_packed)[0]
>>> data
40

使用字符串格式以二进制形式打印。这两种方法都是最好的。bin()不允许您指定要显示的二进制数,如果不需要,则需要删除0b

>>> format(data,'016b')
'0000000000101000'
>>> f'{data:016b}'
'0000000000101000'

你还没有说你想做什么,所以让我们假设你的目标是自学。(如果您试图打包将传递给另一个程序的数据,唯一可靠的测试是检查程序是否正确读取您的输出。)

Python没有"unsigned short"类型,所以struct.pack()的输出是一个字节数组。要查看里面的内容,只需打印出来:

>>> data_packed = struct.pack('<H', 40)
>>> print(data_packed)
b'(x00'

那是什么?字符(,在ascii表中是十进制的40,后面跟着一个空字节。如果您使用了一个不能映射到可打印ascii字符的数字,那么您将看到一些不那么令人惊讶的内容:

>>> struct.pack("<H", 11)
b'x0bx00'

其中0b在十六进制中当然是11。等等,我指定的是"小后缀",那为什么我的号码在左边?答案是,它不是。Python从左到右打印字节字符串,因为这就是英语的书写方式,但这无关紧要。如果有帮助,可以把字符串想象成向上增长:从低内存位置到高内存位置。

无论如何,你也可以直接查看字节:

>>> print(data_packed[0])
40

是的,它还在那里。但你说,那些小片段呢?为此,分别对每个字节使用bin():

>>> bin(data_packed[0])
'0b101000'
>>> bin(data_packed[1])
'0b0'

你看到的两个高位分别是32和8。您的数字小于256,因此它完全适合您构造的short的低字节。

你的拆包代码有什么问题?

只是为了好玩,让我们看看你在get_bin_str中的变换序列是怎么做的。

>>> binascii.hexlify(data_packed)
b'2800'

嗯,好吧。不知道为什么要转换为十六进制数字,但现在您有4个字节,而不是两个。(28是十六进制的数字40,00是空字节。)在下一步中,调用decode并告诉它这4个字节实际上是UTF-16;只够两个unicode字符,让我们看一下:

>>> b'2800'.decode("utf-16-le")
'㠲〰'

在下一步中,Python最终注意到有些地方出错了,但到那时它已经没有太大的区别了,因为你已经离你开始的数字40很远了。

要正确地将数据读取为UTF-16字符,请直接在您打包的字节串上调用decode

>>> data_packed.decode("utf-16-le")
'('
>>> ord('(')
40

最新更新