在struct.unpack格式字符串的中间切换字节序

时间:2018-02-17 19:51:21

标签: python struct endianness

我有一堆二进制数据(视频游戏保存文件的内容,当它发生时),其中一部分数据包含little-endian big-endian整数值。天真的,没有读过很多文档,我试着以这种方式解压缩......

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字段的字节顺序(将其解析为little-endian,当我真的想将其解析为big-endian时)。

是否有一个简单的和/或&#34; Pythonic&#34;解决我的问题?我已经想到了三种可能的解决方案,但它们都没有特别优雅。如果没有更好的想法,我可能会选择3号:

  1. 我可以提取子字符串并单独解析它:

    (my.f1, my.f2, ...) = struct.unpack('<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s', string_data)
    my.f11 = struct.unpack('>I', string_data[56:60])
    
  2. 事后我可以flip the bits in the field

    (my.f1, my.f2, ...) = struct.unpack('<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s', string_data)
    my.f11 = swap32(my.f11)
    
  3. 我可以改变我的下游代码,期望这个字段的表示方式不同 - 它实际上是一个位掩码,而不是算术整数,所以它也不会

1 个答案:

答案 0 :(得分:0)

聚会晚了一点,但是我也遇到了同样的问题。我使用自定义numpy dtype解决了该问题,该类型允许混合具有不同字节序的元素(请参见https://numpy.org/doc/stable/reference/generated/numpy.dtype.html):

t=np.dtype('>u4,<u4') # Compound type with two 4-byte unsigned int with different byte order
a=np.zeros(shape=1, dtype=t) # Create an array of length one with above type
a[0][0]=1 # Assign first uint
a[0][1]=1 # Assign second uint
bytes=a.tobytes() # bytes should be b'\x01\x00\x00\x00\x00\x00\x00\x01'
b=np.frombuffer(buf, dtype=t) # should yield array[(1,1)]
c=np.frombuffer(buf, dtype=np.uint32) # yields array([       1, 16777216]