簡體   English   中英

Python:從二進制數據中解壓結構數組的最佳方法是什么

[英]Python: What's the best way to unpack a struct array from binary data

我正在解析二進制文件格式(OpenType 字體文件)。 該格式是許多不同結構類型的復雜樹,但一個重復出現的模式是具有特定格式的記錄數組。 我使用struct.unpack編寫代碼一次獲取一條記錄。 但我想知道是否有一種方法可以解析整個記錄數組?

以下是一種特定記錄數組的解壓縮結果示例:

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

這就是我目前正在做的事情:我創建了一個通用的 function 來解壓縮任意記錄數組(在任何給定調用中的記錄格式一致)。

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")

因此,我正在遍歷緩沖區(字節序列數據),獲取順序切片並一次一個地解包記錄,為每條記錄創建一個字典並將它們附加到array列表中。

有沒有更好的方法來做到這一點,比如在某個模塊中unpack的方法允許將格式定義為結構數組並立即解包整個 shebang?

看看 kaitai - https://kaitai.io/ ,一個用於跨多種語言解析二進制文件的庫,具有以獨立於語言的方式定義文件格式的框架。

它能夠在文件格式中定義條件,並根據需要調整解析。 雖然學習曲線並非立即微不足道,但也不是太難。


假設您想自己做而不是使用外部庫,則需要考慮一些可以提高性能/代碼的事情:

  1. 使用struct.unpack_from(format, buffer, offset=0)而不是當前方法,因為buffer[index: index + recordLength]可能會創建新對象並復制 memory ,這不是必需的
  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) ]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM