8.3 文件与目录——二进制处理 struct 用法¶
内容梗概¶
本节课解决上一节遗留的痛点:手动逐字段解析二进制文件非常费劲。老师先类比 C 语言中"定义结构体再整体读取"的思路,引出 Python 标准库 struct。课程重点讲解了 struct.unpack 的 format 格式字符串编写规则——字节顺序修饰符(小端 <)与各字段类型符号(s、i、h 等)——并用 struct.unpack('<2sIhhi', buffer) 一行代码完成了 BMP 文件头 14 字节的解析,与上一节的手动转换形成鲜明对比。
知识点详解¶
从 C 语言结构体说起(约 00:00 - 03:00)¶
- 上一节手动解析时,每读一个字段都要思考怎么把它正确转换成想要的类型,非常费劲。
- 类比 C 语言:如果知道一段 14 字节数据的布局(2 字节 + 4 字节 + 2 字节 + 2 字节 + 4 字节),有经验的程序员会定义一个结构体
struct: char magic_number[2](两个字符)int size(4 字节)short reserved1、short reserved2(各 2 字节)int offset(4 字节,位图数据偏移)- 把 14 个字节按这个结构一次性读入,就能自动按正确的类型拆解出每个字段。Python 中对应的功能就是标准库
struct。
struct 库的两个核心方法(约 03:00 - 04:20)¶
struct有两个非常重要的方法:pack:把一堆变量按各自对应的类型和长度打包成二进制数据;unpack:本课重点,分析 BMP 时用的就是它。给定一个 buffer(二进制数据,如 14 字节的文件头)和一个 format 格式规则,一步到位地把 buffer 翻译成各个 Python 变量。
unpack 的 format 格式字符串规则(约 04:51 - 09:40)¶
- 调用形式:
struct.unpack(format, buffer),问题关键在于 format 怎么写,可查官方文档的格式字符串说明。 - 字节顺序修饰符:format 开头标明大端/小端。绝大多数个人电脑(PC)是小端,用**小于号
<** 表示。它是修饰符,告诉 unpack 读 buffer 时要把字节顺序反过来才是正确的数据(呼应上一节手动倒序size[::-1]的操作)。 - 类型符号(对照 C 语言类型):
i:整数,标准大小 4 字节;I(大写):无符号整数unsigned int;h:短整型short(2 字节);H:无符号 short;s:字节串/字符串,前面加数字表示字符个数,如2s表示 2 个字符。- BMP 文件头对应关系:
BM两个字符 →2s- 文件大小 4 字节,不可能是负数 →
I - 两个保留字段各 2 字节 →
H、H - 偏移量 4 字节,偏移不会是负的 →
I - 拼起来并加上小端修饰符:
'<2sIhhi'(字幕口述为"二s i hh i 加小于号";按讲解逻辑两个保留字段用无符号 short,写作HH亦符合规则)。
unpack 的返回值与元组解包(约 10:40 - 12:30)¶
unpack返回一个**元组**,元素个数正好对应 format 中类型的个数:2s一个、I一个、H一个、H一个、I一个,共 5 个。- 利用 Python 的元组解包
a, b, c, d, e = ...可以直接把 5 个值分别赋给magic_number、size、r1、r2、offset等变量,随后直接print即可。 - 信息头 40 字节留给大家自己对照格式表分析,思路相同。
示例与演示¶
- 在 C 语言风格的白板上演示:画 14 字节布局图,写出对应的
struct结构体定义,说明"整体读入、按结构拆解"的思路。 - 改造上一节的
analyzer.py:删掉手动倒序、hex、int转换的一堆代码,替换为: 运行后直接打印出 magic number、文件大小、位图数据偏移等所有字段,无需再手动抠字节、查 API 逐个转换。
重点与难点¶
- **format 字符串的编写**是核心:先写字节顺序修饰符(小端
<),再按字段顺序写类型符号;类型符号与 C 语言类型一一对应(i/I、h/H、s加数量)。 - 要根据字段语义判断有符号还是无符号:文件大小、偏移量不可能是负数,用大写(无符号);保留字段同理。
unpack返回元组,配合 Python 元组解包可一次性赋给多个变量。pack(变量 → 二进制)与unpack(二进制 → 变量)互为逆操作,本课只展开unpack。- 字节顺序修饰符自动处理了小端倒序,省去了手动
size[::-1]的步骤。
关联内容¶
- 直接承接 8.2 节手动解析 BMP 文件头的痛点,是同一
analyzer.py示例的升级版。 - 与 C 语言结构体知识关联(类比引入);用到之前学过的元组解包、字节序(大端/小端,上学期讲过)等前置知识。
- 解析二进制文件格式的能力是 8.6 节作业"猫鼠游戏"(读取文件头特征识别伪装文件)可直接使用的工具。
- 作为标准库的典型例子,为下一节(第 9 章)系统介绍 Python 标准库做铺垫。