Skip to content

Python学习笔记-struct处理二进制数据

Struct打包字节

简介

Python 的 struct 模块是一个标准库模块,主要作用是 在 Python 的数据类型与二进制数据之间进行转换。 可以加字节序前缀来标识字节序,可选项为 <(小端)、>(大端)、!(网络字节序=大端)

大端序(Big-Endian)

  • 高位字节放在低地址(前面)

  • 低位字节放在高地址(后面)

  • 直观理解就是 “人类习惯的书写顺序”:先写高位,再写低位

小端序(Little-Endian)

  • 低位字节放在低地址(前面)

  • 高位字节放在高地址(后面)

  • 直观理解就是 “低位在前,高位在后”

类型

格式 C 类型 Python 类型 字节数 描述
x pad byte 1 填充字节,不存储数据
c char bytes of length 1 1 单个字符
b signed char int 1 有符号 8 位整数 (-128\~127)
B unsigned char int 1 无符号 8 位整数 (0\~255)
h short int 2 有符号 16 位整数
H unsigned short int 2 无符号 16 位整数
i int int 4 有符号 32 位整数
I unsigned int int 4 无符号 32 位整数
l long int 4 有符号 32 位整数
L unsigned long int 4 无符号 32 位整数
q long long int 8 有符号 64 位整数
Q unsigned long long int 8 无符号 64 位整数
f float float 4 单精度浮点数
d double float 8 双精度浮点数
s char[] bytes n 固定长度字符串,例如 '5s' 表示 5 字节字符串
p char[] bytes n Pascal 风格字符串,第一个字节表示长度
? _Bool bool 1 布尔值

示例一

有type,version,size,data四个字段,分别对应4字节,1字节,4字节,任意字节。其中type和version为头部信息,size为数据长度,data为数据。

import struct

version = 1
type=1
data = "hello"
size = len(data)


init_head = struct.pack('>IB', type, version)
data_length = struct.pack('>I', size)

# 组合数据
all_data = init_head + data_length + data.encode("utf-8")

# 解包
# I 长度为4,B长度为1,所以这两个结合起来为5字节
init_head = struct.unpack('>IB', all_data[:5])
data_length = struct.unpack('>I', all_data[5:9])
data = all_data[9:]

示例二

有version和type两个字段,一共占用1个字节,version 占用6bit,type 占用2bit

import struct

version = 25
type=5

# 将version和type合并为1个字节
merge_data = struct.pack('B', (version << 2) | type)
# 解包
type = merge_data >> 2
# 这个11指的是掩码,因为低位占2位,所以是两个1,如果是4位,那就是0xF(可以用二进制,也可以用16进制)
version = merge_data & 0x11

示例二的合并与解包过程

# 合并步骤
# 步骤1:将version 转成二进制
25 = 0001 1001
# 步骤2:将type 转成二进制
3 = 0000 0011
# 步骤3:采用的大端序,高位在前,低位在后,type作为低位,需要2bit,所以version左移2位
25 << 2 = 100 = 0110 0100
# 步骤4:合并
0110 0100 | 0000 0011 = 0110 0111

# 解包步骤
# 步骤1:将合并后的数据右移2位,将version取出
0110 0111 >> 2 = 0001 1001 = 25
# 步骤2:获取type
0110 0111 & 0000 0011 = 0000 0011 = 3