Python struct打包小端无符号短整型后如何正确解码获取二进制值
问题描述
使用如下代码将整数打包为小端无符号短整型:
raw_data = 40 # Pack into little endian data_packed = struct.pack('<H', raw_data)
尝试对打包结果解包获取二进制字符串时,误将小端字节序等同于utf-16-le编码,写出如下代码:
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: invalid literal for int() with base 16: '㠲〰'
需要找到正确解码小端字节序数据、得到对应二进制值的方法。
错误原因
核心问题是混淆了字节序和字符编码两个完全独立的概念:
utf-16-le是UTF-16字符编码的小端变体,仅用于Unicode字符与字节序列的转换,和数值的字节序处理没有任何关系。- 整数40打包为小端无符号短整型后,原始字节为
b'(\x00'(对应十六进制值0x0028,小端规则下低字节在前,存储顺序为0x28、0x00)。binascii.hexlify(data_packed)返回的是十六进制表示对应的ASCII字节b'2800',四个字节分别对应ASCII字符'2'、'8'、'0'、'0'。此时用utf-16-le解码,会每两个字节拼接为一个Unicode字符,最终得到乱码㠲〰,不是合法的十六进制数字串,传入int()做进制转换必然报错。
正确实现方案
不需要做多余的编码转换,两种常用实现方式如下:
方案1:使用struct对称解包
和打包逻辑对应,直接用相同格式符通过struct.unpack解包得到原始整数,再转换为二进制字符串即可,是最稳妥的实现方式:
import struct raw_data = 40 data_packed = struct.pack('<H', raw_data) # 按小端无符号短整型格式解包 unpacked_num = struct.unpack('<H', data_packed)[0] # 转二进制字符串,去掉前缀0b bin_str = bin(unpacked_num)[2:] print(bin_str) # 输出:101000
方案2:手动按小端规则拼接二进制位
如果不想依赖struct模块,可以手动按小端「低字节在前、高字节在后」的规则,逐字节转二进制后拼接:
def get_bin_str(data): bin_str = '' # 小端存储低字节在前,反转后从高字节开始拼接 for byte in reversed(data): # 每个字节固定转8位二进制,不足8位前补0 bin_str += f'{byte:08b}' # 去除前导多余的0 return bin_str.lstrip('0') print(get_bin_str(data_packed)) # 输出:101000
内容的提问来源于stack exchange,提问作者user1241241
相关产品推荐
相关产品推荐

