【发布时间】:2018-07-28 10:56:27
【问题描述】:
我有一堆二进制数据(恰好是视频游戏保存文件的内容),其中一部分数据同时包含小端 和 大端整数值。天真地,没有阅读太多文档,我试图以这种方式解压它......
struct.unpack(
'3sB<H<H<H<H4s<I<I32s>IbBbBbBbB12s20sBB4s',
string_data
)
...当然,我收到了这条神秘的错误消息:
struct.error: bad char in struct format
问题在于struct.unpack 格式字符串不期望单个字段 被标记为字节序。此处实际正确的格式字符串类似于
struct.unpack(
'<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s',
string_data
)
除了这将翻转第三个I 字段的字节序(当我真的想将其解析为大字节序时,将其解析为小字节序)。
我的问题有简单和/或“Pythonic”的解决方案吗?我已经想到了三种可能的解决方案,但没有一个是特别优雅的。如果没有更好的想法,我可能会选择 3:
-
我可以提取一个子字符串并单独解析它:
(my.f1, my.f2, ...) = struct.unpack('<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s', string_data) my.f11 = struct.unpack('>I', string_data[56:60]) -
事后我可以flip the bits in the field:
(my.f1, my.f2, ...) = struct.unpack('<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s', string_data) my.f11 = swap32(my.f11) 我可以更改我的下游代码以期望该字段以不同的方式表示 - 它实际上是一个位掩码,而不是算术整数,因此它不会太难以翻转我使用的所有位掩码;但这些位掩码的大端版本比小端版本更具有助记性。
【问题讨论】:
-
我认为这里在概念上有些问题。不应该有字节序混合。该修复会影响您需要解压缩的字符串的来源。关于下游代码选项。这处理一个 int (已经转换),它自动使用它运行的机器的字节序。
-
@CristiFati:我解压的字符串来自游戏存档文件格式。我不控制它的编码细节;我无法改变它们。我所能做的就是尝试处理给我的编码,给我的编码确实以这种精确的方式混合字节序。
-
作为更广泛的示例,ISO 9660 文件系统在某些地方将整数编码为小端和大端。通常是这样,您可以选择更容易在您的架构上使用的格式,但如果检查数据的完整性,解码两者并检查它们是否相等可能会很有用。
标签: python struct endianness