我使用Python将一些文件转换为二进制格式,但我遇到了一个奇怪的陷阱。
import struct
s = struct.Struct('Bffffff')
print s.size
28
显然预期的大小为25
,但似乎是将第一个字节(B
)解释为某种4字节整数。它还会写出一个4字节的整数而不是一个字节。
存在一种变通方法,即将B
分离为单独的struct
,如下所示:
import struct
s1 = struct.Struct('B')
s2 = struct.Struct('ffffff')
print s1.size + s2.size
25
这种行为有什么解释吗?
答案 0 :(得分:6)
来自docs
填充仅在连续的结构成员之间自动添加。在编码结构的开头或结尾没有添加填充。
如果你测试
>>> import struct
>>> s1 = struct.Struct('B')
>>> print s1.size
1
>>> s1 = struct.Struct('f')
>>> print s1.size
4
所以当你添加时它是25
...但反过来说,B
是1,其余的是4
所以它将被填充以使其成为{{1}所以答案是4
考虑这个例子
28
此处>>> s1 = struct.Struct('Bf')
>>> print s1.size
8
再次B
并填充1
,3
为f
,因此最终达到4
,这与预期一致
如前所述here要覆盖它,你将不得不使用非本地方法
8
使用非原生大小和对齐时,不添加填充,例如使用'<','>','='和'!'。
答案 1 :(得分:4)
除非为字节顺序指定任何字符,否则struct
使用本机字节顺序,对齐(@
);这会导致填充。
通过明确指定字节顺序,您可以获得所需内容:
>>> struct.Struct('!Bffffff').size # network byte order
25
>>> struct.Struct('=Bffffff').size # native byte order, no alignment.
25
>>> struct.Struct('>Bffffff').size # big endian
25
>>> struct.Struct('<Bffffff').size # little endian
25
>>> struct.Struct('@Bffffff').size # native byte order, alignment. (+ native size)
28