Quu*_*one 6 python struct endianness
我有一堆二进制数据(视频游戏保存文件的内容,因为它发生),其中一部分数据包含小端和大端整数值。天真地,在没有阅读大量文档的情况下,我试图以这种方式打开它......
struct.unpack(
'3sB<H<H<H<H4s<I<I32s>IbBbBbBbB12s20sBB4s',
string_data
)
Run Code Online (Sandbox Code Playgroud)
...当然我收到了这个神秘的错误消息:
struct.error: bad char in struct format
Run Code Online (Sandbox Code Playgroud)
问题是struct.unpack格式字符串不希望单个字段被标记为字节序。此处实际正确的格式字符串类似于
struct.unpack(
'<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s',
string_data
)
Run Code Online (Sandbox Code Playgroud)
除了这将翻转第三个I字段的字节序(将其解析为小端,当我真的想将其解析为大端时)。
我的问题有简单和/或“Pythonic”的解决方案吗?我已经想到了三种可能的解决方案,但没有一个是特别优雅的。如果没有更好的想法,我可能会选择第 3 条:
我可以提取一个子字符串并单独解析它:
(my.f1, my.f2, ...) = struct.unpack('<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s', string_data)
my.f11 = struct.unpack('>I', string_data[56:60])
Run Code Online (Sandbox Code Playgroud)事后我可以翻转字段中的位:
(my.f1, my.f2, ...) = struct.unpack('<3sBHHHH4sII32sIbBbBbBbB12s20sBB4s', string_data)
my.f11 = swap32(my.f11)
Run Code Online (Sandbox Code Playgroud)我可以改变我的下游代码以期望这个字段以不同的方式表示——它实际上是一个位掩码,而不是一个算术整数,所以翻转我正在使用的所有位掩码不会太难;但是这些位掩码的 big-endian 版本比 little-endian 版本在助记方面更相关。
聚会有点晚了,但我也遇到了同样的问题。我用自定义 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]
Run Code Online (Sandbox Code Playgroud)