假设Python的struct.pack方法不一致

时间:2018-02-09 08:50:39

标签: python binary pack

我现在很困惑。

如果我打包一个7长度的二进制字符串,结果如下:

>>> struct.pack('7s',b'\x1fBLOCK\n')
b'\x1fBLOCK\n'

此外,如果我打包一个unsigned long long,结果是:

>>> struct.pack('1Q',126208)
b'\x00\xed\x01\x00\x00\x00\x00\x00'

但是,如果我将两者打包在一起,则reuslt会增加一个额外的字节:

>>> struct.pack('7s1Q',b'\x1fBLOCK\n',126208)
b'\x1fBLOCK\n\x00\x00\xed\x01\x00\x00\x00\x00\x00'

任何人都知道为什么会出现这个额外字节?

  

b' \ x1fBLOCK \ n \ x00 \ x00 \ xed \ x01 \ x00 \ x00 \ x00 \ x00 \ x00'

这个事实破坏了自定义文件的二进制读取......

3 个答案:

答案 0 :(得分:2)

struct.pack生成的字节布局(默认情况下)将与平台C编译器生成的字节匹配,后者可能包括字段之间的填充字节。您可以通过在格式字符串的开头添加=来禁用此行为:

> struct.pack('7s1Q',b'\x1fBLOCK\n',126208) # C-style layout with padding bytes
'\x1fBLOCK\n\x00\x00\xed\x01\x00\x00\x00\x00\x00'
> struct.pack('=7s1Q',b'\x1fBLOCK\n',126208) # No padding
'\x1fBLOCK\n\x00\xed\x01\x00\x00\x00\x00\x00'

答案 1 :(得分:1)

似乎我使用了@标志,这意味着字节顺序是本地字节顺序,因此最终大小是可变的。

解决方案在于使用固定大小的标记,例如<>!=

>>> struct.pack('<7s1Q',b'\x1fBLOCK\n',126208)
b'\x1fBLOCK\n\x00\xed\x01\x00\x00\x00\x00\x00'

答案 2 :(得分:0)

附加\x00是字符串终止字节 - 在C中,字符串以\x00结束。

您将字符串连接到unsigned long long,所以

  

注意默认情况下,打包给定C结构的结果包括填充字节,以便维护所涉及的C类型的正确对齐

applies

https://docs.python.org/3/library/struct.html#format-characters

b'\x1fBLOCK\n\x00   \x00\xed\x01\x00\x00\x00\x00\x00'  
    1 23456 7  8th   1   2   3   4   5   6    7   8