Python struct模块读写二进制数据(附带实例)
有的时候需要用 Python 处理二进制数据,如存取文件或 socket 通信时,可以使用 Python 的 struct 模块完成,用 struct 模块处理 C语言中的结构体。
结构体在 C语言中定义了一种结构,包含不同类型的数据(int、char、bool 等),可方便对某一结构对象进行处理。在网络通信中,传输的数据大多是以二进制流(Binary Data)的形式存在的,当传输字符串时,不必担心太多的问题,当传输诸如 int、char 之类的基本数据时,就需要有一种机制,先将某些特定的结构体类型打包成二进制流的字符串,再通过网络传输,接收端通过某种机制解包还原出原始的结构体数据。
Python 中的 struct 模块就提供了这样的机制。该模块的主要作用是对 Python 基本数据类型与用 Python 字符串格式表示的 C语言 struct 类型进行转换。
struct 模块中最重要的函数为 pack()、unpack() 和 calcsize():
测试代码为:
注意,格式化字符串的值在 Python3 中的类型是 bytes 类型,需要在 bytes 类型前面加上一个 b 后,再通过 struct 的 pack 打包,并制定 format'I4s' 的规则,I 表示 int,4s 表示三个字符长度的字符串。
由输出结果可知,data 被 pack 之后,首先转化为一段二进制字节串,然后通过 struct 的 unpack 对打包的二进制数据进行解包,将字节串再转换回元组。
定义 format 可以参照官方 API 提供的对照表,如下表所示:
struct.calcsize 用于计算格式字符串对应的长度,如 struct.calcsize('ii') 返回 8,因为两个 int 数据类型占用的长度是 8 个字节,代码为:
结构体在 C语言中定义了一种结构,包含不同类型的数据(int、char、bool 等),可方便对某一结构对象进行处理。在网络通信中,传输的数据大多是以二进制流(Binary Data)的形式存在的,当传输字符串时,不必担心太多的问题,当传输诸如 int、char 之类的基本数据时,就需要有一种机制,先将某些特定的结构体类型打包成二进制流的字符串,再通过网络传输,接收端通过某种机制解包还原出原始的结构体数据。
Python 中的 struct 模块就提供了这样的机制。该模块的主要作用是对 Python 基本数据类型与用 Python 字符串格式表示的 C语言 struct 类型进行转换。
struct 模块中最重要的函数为 pack()、unpack() 和 calcsize():
- pack(fmt, v1, v2,…),按照给定的格式(fmt)把数据封装成字符串(实际上是类似于 C语言中结构体的字节流);
- unpack(fmt, string),按照给定的格式(fmt)解析字节流 string,返回解析出来的tuple(元组);
- calcsize(fmt):计算给定的格式(fmt)占用多少字节的内存。
测试代码为:
>>> import struct >>> import binascii >>> p_data = struct.pack('I4s', *data) >>> print(binascii.hexlify(p_data)) b'01000000061626364' >>> unp_data = struct.unpack('I4s',p_data) >>> type(unp_data) <class 'tuple'> >>> print(unp_data) (1, b'abcd')在测试代码中,首先定义了一个元组,包含 int、bytes 两种数据类型。
注意,格式化字符串的值在 Python3 中的类型是 bytes 类型,需要在 bytes 类型前面加上一个 b 后,再通过 struct 的 pack 打包,并制定 format'I4s' 的规则,I 表示 int,4s 表示三个字符长度的字符串。
由输出结果可知,data 被 pack 之后,首先转化为一段二进制字节串,然后通过 struct 的 unpack 对打包的二进制数据进行解包,将字节串再转换回元组。
定义 format 可以参照官方 API 提供的对照表,如下表所示:
format | C Type | Python Type | Seanrdard Size |
---|---|---|---|
x | pad byte | no value | |
c | char | bytes of length 1 | 1 |
b | signed char | integer | 1 |
B | unsigned char | integer | 1 |
? | _Bool | bool | 1 |
h | short | integer | 2 |
H | unsigned short | integer | 2 |
i | int | integer | 4 |
I | unsigned int | integer | 4 |
l | long | integer | 4 |
L | unsigned long | integer | 4 |
q | long long | integer | 8 |
Q | unsigned long long | integer | 8 |
n | size_t | integer | |
N | size_t | integer | |
e | (7) | float | 2 |
f | float | float | 4 |
d | double | float | 8 |
s | char[] | bytes | |
P | char[] | bytes | |
p | void * | integer |
struct.calcsize 用于计算格式字符串对应的长度,如 struct.calcsize('ii') 返回 8,因为两个 int 数据类型占用的长度是 8 个字节,代码为:
>>> print(struct.calcsize('i')) 4 >>> print(struct.calcsize('ii')) 8 >>> print(struct.calcsize('s')) 1 >>> print(struct.calcsize('is')) 5 >>> print(struct.calcsize('d')) 8 >>> print(struct.calcsize('f')) 4