将“struct”数据存储到二进制文件中

时间:2010-07-02 10:36:51

标签: python header-files binaryfiles

我需要存储一个二进制文件,其中包含一个由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

另外,我有一个npVect浮点数维D(numpy.ndarray - float32)。我怎么能将这个向量存储在同一个二进制文件中,但是在标题之后?

2 个答案:

答案 0 :(得分:2)

正如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代码以在打包之前展平数组,并在解压缩后重新构建它。

答案 1 :(得分:1)

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

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