Python: 从二进制数据解压结构数组的最佳方法是什么?

问题描述 投票:0回答:1

我正在解析一个二进制文件格式(OpenType字体文件)。该格式是一棵复杂的树,由许多不同的结构类型组成,但一个反复出现的模式是有一个特定格式的记录数组。我已经写了代码,使用 struct.unpack 每次只获取一条记录。但我想知道是否有我遗漏的方法来解析整个记录数组?

下面是一种特殊记录数组的解包结果的例子。

[{'glyphID': 288, 'paletteIndex': 0}, {'glyphID': 289, 'paletteIndex': 1}, {'glyphID': 518, 'paletteIndex': 0}, ...]    list

这是我目前正在做的事情。我创建了一个通用函数来解包一个任意记录数组(在任何一次调用中都保持一致的记录格式)。

def tryReadRecordsArrayFromBuffer(buffer, numRecords, format, fieldNames):
    recordLength = struct.calcsize(format)
    array = []
    index = 0
    for i in range(numRecords):
        record = {}
        vals = struct.unpack(format, buffer[index : index + recordLength])
        for k, v in zip(fieldNames, vals):
            record[k] = v
        array.append(record)
        index += recordLength

    return array

这个 buffer 参数是一个至少是数组大小的字节序列,第一条记录在序列的开始处被解包。

列表中的 format 参数是一个 struct 格式字符串,根据被读取的记录数组的类型。在一种情况下,格式字符串可能是 ">3H"在另一种情况下,它可能是 ">4s2H";等。对于上述结果的例子,是 ">2H".

fieldNames 参数是指定记录类型中字段名的字符串序列。在上面的结果示例中,参数是 ("glyphID", "paletteIndex").

所以,我通过缓冲区(字节序列数据),获得连续的片断,然后一次一次解压记录,为每条记录创建一个dict,并将它们附加在 array 列表。

是否有更好的方法,像 unpack 在某个模块中,允许将格式定义为一个结构数组,并一次性解包整个结构?

python arrays binaryfiles
1个回答
0
投票

看看kaitai - https:/kaitai.io它是一个跨语言解析二进制文件的库,它的骨架可以以独立于语言的方式定义文件格式。

它能够在文件格式内部定义条件,并根据需要调整解析。虽然学习曲线并不是马上就能完成的,但也不是太难。


假设你想自己做,而不是使用外部库,有一些事情可以考虑,可以改善perforamcecode。

  1. 使用 struct.unpack_from(format, buffer, offset=0) 而不是当前的方法,如 buffer[index : index + recordLength] 可能会创建新的对象,并复制不必要的内存。
  2. 如果你想解压一个相同格式的数组,你可以通过使用 struct.iter_unpack(format, buffer) 然后对结果进行迭代。

    import itertools
    import struct
    
    def tryReadRecordsArrayFromBuffer(buffer, numRecords, format, fieldNames):
        unpack_iter = struct.iter_unpack(buffer, format)
        return [
            # I like this better than dict(zip(...)) but you can also do that
            {k: v for k, v in zip(fieldNames, vals)}
            # We use `islice` to only take the first numRecords values
            for vals in itertools.islice(unpack_iter, numRecords)
        ]
    
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.