gpt4 book ai didi

有多个字节顺序时的Python struct.unpack(ing)?

转载 作者:行者123 更新时间:2023-12-03 20:21:47 59 4
gpt4 key购买 nike

我有一个读取二进制文件然后使用 struct.unpack() 解压文件内容的函数。我的功能工作得很好。如果/当我使用长的“格式”字符串解压缩整个文件时,它会更快。问题是有时字节对齐会发生变化,因此我的格式字符串(无效)看起来像'<10sHHb>llh'(这只是一个示例(它们通常更长))。是否有任何超光滑/pythonic 的方式来处理这种情况?

最佳答案

没有什么 super 流畅,但如果速度很重要,struct模块顶级函数是包装器,必须反复检查缓存中的实际 struct.Struct对应格式字符串的实例;虽然您必须制作单独的格式字符串,但您可以通过避免重复的缓存检查来解决部分速度问题。

而不是这样做:

buffer = memoryview(somedata)
allresults = []
while buffer:
allresults += struct.unpack_from('<10sHHb', buffer)
buffer = buffer[struct.calcsize('<10sHHb'):]
allresults += struct.unpack_from('>llh', buffer)
buffer = buffer[struct.calcsize('>llh'):]

你会这样做:
buffer = memoryview(somedata)
structa = struct.Struct('<10sHHb')
structb = struct.Struct('>llh')
allresults = []
while buffer:
allresults += structa.unpack_from(buffer)
buffer = buffer[structa.size:]
allresults += structb.unpack_from(buffer)
buffer = buffer[structb.size:]

不,它看起来并没有更好看,而且速度的提高也不可能让你大吃一惊。但是你有奇怪的数据,所以这是最不脆弱的解决方案。

如果您想要不必要的聪明/脆弱的解决方案,您可以使用 ctypes定制 Structure s, 嵌套 BigEndianStructure (s) 在 LittleEndianStructure 内或相反亦然。对于您的示例格式:
from ctypes import *

class BEStruct(BigEndianStructure):
_fields_ = [('x', 2 * c_long), ('y', c_short)]
_pack_ = True

class MainStruct(LittleEndianStructure):
_fields_ = [('a', 10 * c_char), ('b', 2 * c_ushort), ('c', c_byte), ('big', BEStruct)]
_pack_ = True

会给你一个结构,你可以这样做:
mystruct = MainStruct()
memoryview(mystruct).cast('B')[:] = bytes(range(25))

然后您将按预期顺序获得结果,例如:
>>> hex(mystruct.b[0])  # Little endian as expected in main struct
'0xb0a'
>>> hex(mystruct.big.x[0]) # Big endian from inner big endian structure
'0xf101112'

虽然在某种程度上很聪明,但它可能会运行得更慢(根据我的经验, ctypes 属性查找速度非常慢),并且与 struct 不同。模块函数,你不能只在一行中解压到顶级命名变量,它是一路属性访问。

关于有多个字节顺序时的Python struct.unpack(ing)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54819833/

59 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com