问题描述
我正在从C程序向STDOUT发送二进制形式的1.0和2.0:
float array[2] = { 1.0,2.0 };
fwrite(&array[0],sizeof(array[0]),sizeof(array) / sizeof(array[0]),stdout);
fflush(stdout);
Python程序将STDOUT读取为:
b'\x00\x00\x80?\x00\x00\x00@'
当我尝试将其转换回浮点型时,这可行:
struct.unpack('<f',array[0:4]) # 1.0
struct.unpack('<f',array[4:8]) # 2.0
但是,如果我尝试一次解码整个数组,它将失败:
struct.unpack('<f',array)
并显示以下消息:
error: unpack requires a buffer of 4 bytes
是否可以一次解码整个数组,还是应该在循环中分别解码每个浮点数?
解决方法
使用结构
基于struct module documentation,struct.unpack()
函数必须具有定义的准确格式,才能一次解压缩多个值。因此,如果需要使用struct
模块,则必须使用'<ff'
格式定义格式,或者使用struct.iter_unpack(format,buffer)遍历数组。
使用数组
另一种选择是使用array模块,该模块允许您立即解码二进制数据。您可以使用array.byteswap()方法更改字节序。唯一的限制是整个数组必须具有相同的类型。
import array
arr = array.array('f',b'\x00\x00\x80?\x00\x00\x00@')
arr.tolist()
# [1.0,2.0]
# change endianness
arr.byteswap()
arr.tolist()
# [4.600602988224807e-41,8.96831017167883e-44]
,
Python的strcut提供了一些必要的工具,但是使用起来有些笨拙。 特别是为此,它必须将所有浮点数生成为Python浮点数的元组(每个都是10字节的“巨大” objetcs),然后将其插入到数组中。
幸运的是,Python的array.array
类本身可以在给定byte对象的情况下填充其值,甚至可以直接从文件中读取该值。
import array
data = b'\x00\x00\x80?\x00\x00\x00@'
arr = array.array('f')
arr.frombytes(data)
print(arr)
收益:
array('f',[1.0,2.0])
(要直接从文件中读取,请使用fromfile
方法)