繁体   English   中英

将“结构”数据存储到二进制文件

[英]Storing 'struct' data to binary file

我需要存储一个包含4个字段的12字节标头的二进制文件。 它们分别是:sSamples(4字节整数),sSampPeriod(4字节整数),sSampSize(2字节整数),最后是sParmKind(2字节整数)。 我使用'struct'到我想要的字段的变量。 现在,我已经分别定义了它们,如何合并它们以存储“ 12个字节的标头”?

sSamples        = struct.pack('i', nSamples) # 4-bytes integer
sSampPeriod     = struct.pack('i', nSampPeriod) # 4-bytes integer
sSampSize       = struct.pack('H', nSampSize) # 2-bytes integer / unsigned short
sParmKind       = struct.pack('H', 9) # 2-bytes integer / unsigned short

另外,我有一个维度为D的npVect浮点数组( numpy.ndarray -float32)。 如何将这个向量存储在相同的二进制文件中,但在标头之后?

正如Cody Brocious所写,您可以一次打包整个标头:

header = struct.pack('<iiHH', nSamples, nSampPeriod, nSampSize, nParmKind)

他还提到字节顺序,字节序对于要打包数据以便在具有不同体系结构的机器上可靠地解压缩数据非常重要。 我的格式字符串开头的<表示“使用Little-endian约定打包此数据”。

至于数组,您必须打包其长度才能确定再次读取时要解包的值。 一次调用即可完成所有操作:

flattened = npVect.ravel()  # get a 1-D array of numbers
arrSize = len(flattened)
# pack header, count of numbers, and numbers, all in one call
packed = struct.pack('<iiHHi%df' % arrSize,
    nSamples, nSampPeriod, nSampSize, nParmKind, arrSize, *flattened)

根据数组的大小,您可能会得到一个巨大的字符串,该字符串代表二进制文件的全部内容,并且您可能想研究struct替代方法,这些方法不需要您将整个文件放入记忆。

开箱:

fmt = '<iiHHi'
nSamples, nSampPeriod, nSampSize, nParmKind, arrSize = struct.unpack(fmt, packed)
# Use unpack_from to start reading after the packed header and count
flattened = struct.unpack_from('<%df' % arrSize, packed, struct.calcsize(fmt))
npVect = np.ndarray(flattened, dtype='float32').reshape(# your dimensions go here
    )

编辑 :糟糕,数组格式不是那么简单:)虽然,总的想法仍然存在:使用您喜欢的任何方法将数组展平为数字列表,打包数值的数量,然后打包每个数值。 另一方面,将数组作为平面列表读取,然后将所需的结构强加于其上。

编辑 :更改格式的字符串以使用重复说明符,而不是字符串乘法。 感谢John Machin指出这一点。

编辑 :添加了numpy代码以在打包前将数组弄平并在拆包后对其进行重构。

struct.pack返回一个字符串,因此您可以简单地通过字符串串联来组合字段:

header = sSamples + sSampPeriod + sSampSize + sParmKind
assert len( header ) == 12

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM