struct类用于打包和解包二进制字节流,对于二进制数据的处理至关重要。
pack
pack方法用于将数据打包成字节流,数据可以是数字、字符串、数组,其使用方法为:
import struct
struct.pack(fmt, data)
fmt是格式化的格式,data为数据,fmt的规则为[order][format]
,order为字节顺序,比如小端LE、大端BE等,format就是字节的格式了,可以是字节、整形、浮点数等,比如:
In[13]: struct.pack(">II", *[1, 2])
Out[13]: '\x00\x00\x00\x01\x00\x00\x00\x02'
In[14]: struct.pack("<II", *[1, 2])
Out[14]: '\x01\x00\x00\x00\x02\x00\x00\x00'
以下是详细规则:
字节顺序
Character | Byte order | Size | Alignment |
---|---|---|---|
@ | native | native | native |
= | native | standard | none |
< | little-endian | standard | none |
> | big-endian | standard | none |
! | network (= big-endian) | standard | none |
格式
Format | C Type | Python type | Standard size | Notes |
---|---|---|---|---|
x | pad byte | no value | ||
c | char | string of length | 1 | 1 |
b | signed char | integer | 1 | (3) |
B | unsigned char | integer | 1 | (3) |
? | _Bool | bool | 1 | (1) |
h | short | integer | 2 | (3) |
H | unsigned short | integer | 2 | (3) |
i | int | integer | 4 | (3) |
I | unsigned int | integer | 4 | (3) |
l | long | integer | 4 | (3) |
L | unsigned long | integer | 4 | (3) |
q | long long | integer | 8 | (2), (3) |
Q | unsigned long long | integer | 8 | (2), (3) |
f | float | float | 4 | (4) |
d | double | float | 8 | (4) |
s | char[] | string | ||
p | char[] | string | ||
P | void * | integer | (5), (3) |
注意
首先要注意的是大端小端的问题,这个在上面的例子已经有所体现,如果不加order标志,默认使用的是@
这个order。
其次,使用时如果相对数组使用,必须要加上不定参数标志*
。
unpack
用于解包二进制数据,基本和pack
的用法一致,不过是逆运算,fmt
的格式和pack
一模一样,第二个参数为二进制字节流,返回一个由结果构成的元祖。
In[15]: struct.unpack("<II", '\x01\x00\x00\x00\x02\x00\x00\x00')
Out[15]: (1, 2)
效率
测试表明,打包和解包的性能的确会随着数据量的大小而发生变化。这个变化似乎并不是线性的,在一定数据量以下时,性能并不会成为瓶颈,但当数据量超过某个数量级时,性能会极速恶化,这一点需要注意。