处理二进制文件时,Python的rb模式和struct模块是核心工具,前者负责以二进制形式读取原始字节数据,后者则能将连续的字节流按照指定规则拆解为可识别的Python数据类型。

一、使用rb模式读取二进制文件
Python中打开文件时,模式参数决定文件的读写方式,rb表示以二进制只读模式打开文件,这种模式下读取到的内容不会做任何编码转换,直接返回原始的字节对象bytes。
基础的二进制文件读取代码如下:
# 以rb模式打开二进制文件
with open('test.bin', 'rb') as f:
# 读取全部字节内容
raw_data = f.read()
print(type(raw_data)) # 输出 <class 'bytes'>
print(raw_data) # 输出原始字节,如 b'x01x02x03x04'
使用rb模式需要注意两点:一是文件路径需要正确,若文件不存在会抛出FileNotFoundError;二是读取大文件时,不建议一次性调用read()读取全部内容,可以传入参数指定每次读取的字节数,避免占用过多内存。
二、struct模块解包字节流的核心用法
读取到原始字节流后,需要按照数据的存储规则将其转为对应的Python类型,这时候就需要用到struct模块。struct模块的核心功能是通过格式字符串定义字节的解析规则,再将字节流转为对应的元组。
1. 常用格式字符
struct模块的格式字符对应不同的数据类型和字节长度,常用的格式字符如下:
| 格式字符 | 对应C类型 | Python类型 | 字节长度 |
|---|---|---|---|
| i | int | integer | 4 |
| f | float | float | 4 |
| d | double | float | 8 |
| s | char[] | bytes | 指定长度 |
| ? | _Bool | bool | 1 |
2. 解包函数unpack的使用
struct.unpack(format, buffer)函数接收两个参数,第一个是格式字符串,第二个是要解析的字节流,返回解析后的元组。下面的示例展示了解包4字节整数的过程:
import struct
# 原始字节流,对应一个4字节的整数 1
raw_bytes = b'x01x00x00x00'
# 格式字符串 'i' 表示解析为4字节有符号整数
result = struct.unpack('i', raw_bytes)
print(result) # 输出 (1,)
print(result[0]) # 输出 1
三、完整示例:读取二进制文件并解包字节流
假设我们有一个自定义的二进制文件,存储规则是:前4字节是一个整数表示数据长度,接着4字节是一个浮点数表示数据值,最后是对应长度的字节字符串。下面是完整的读取和解包代码:
import struct
with open('data.bin', 'rb') as f:
# 读取前4字节,解析数据长度
len_bytes = f.read(4)
data_len = struct.unpack('i', len_bytes)[0]
print(f'数据长度: {data_len}')
# 读取4字节,解析浮点数值
val_bytes = f.read(4)
data_val = struct.unpack('f', val_bytes)[0]
print(f'数据值: {data_val}')
# 读取对应长度的字节字符串
str_bytes = f.read(data_len)
data_str = str_bytes.decode('utf-8')
print(f'数据字符串: {data_str}')
如果二进制文件的字节序和当前系统的默认字节序不同,还需要在格式字符串开头添加字节序标识,比如<表示小端字节序,>表示大端字节序,例如struct.unpack('<i', raw_bytes)就是按照小端字节序解析4字节整数。