跳转至

2022-回放-04:Base64 作业讲解 · 数据类型进阶与输入输出复习 · 常见文件格式处理库

内容梗概

本次直播回放分为上下两个半场。上半场完整讲解 base64 编码/解码作业的写法:先画流程图梳理算法与边界条件,再现场敲代码(live coding)实现 encode 与 decode,并借机讲解 bin、format 格式化、bytes 迭代取整、str.count、find 与 index 的区别、int.to_bytes 与字节序等知识。下半场快速串讲"数据类型进阶"与"输入输出"两章录播视频的重点(列表/元组/集合/字典、print 写文件与日志思想),演示了 BMP 图片转 ASCII 字符画的实例,最后扩展介绍了处理各类常见文件格式(zip、tar、csv、Excel、Word、PDF、图像、音频、视频)的 Python 库。整节课反复强调的学习方法是:画流程图梳理思路、用 print 做中间结果验证、遇问题查官方文档。

知识点详解

一、base64 编码作业讲解(约 00:00 - 00:57)

  • 流程图先行(约 00:00):编码流程为:输入 bytes → 全部转为二进制字符串(binary string)→ 每 6 比特一组转成数字 → 从长度为 64 的字符表中按下标取字符拼接。
  • 边界条件(约 00:55):字节数不是 3 的整数倍时需要补位。3 字节 = 24 比特正好被 6 整除;余 1 字节要补 4 个 0、余 2 字节要补 2 个 0,并在结果末尾追加对应数量的 =(余 1 补两个 =,余 2 补一个 =)。
  • bytes 迭代得到的是整数(约 08:31):遍历 bytes 对象时取出的每个元素直接就是该字节对应的整数(int),无需再用 ord 转换——这是与字符串遍历的重要区别。随机生成定长 bytes 用 random.randbytes(n)。
  • bin() 的问题(约 05:30 - 07:10):bin(x) 要求输入为 int,返回形如 0b11 的字符串,且省略前导 0,不能保证 8 位宽度。
  • 自写函数补齐宽度(约 12:00):写 bin_convert(input, length):bin(input) 后用切片 [2:] 去掉 0b,再 while len(result) < length: result = '0' + result 前补 0。写成函数是为了重用(解码时还要补到 6 比特)。
  • format 函数与格式规范迷你语言(约 15:50 - 26:00):format(x, '08b') 一步到位:第二个参数是格式规范(format specification mini-language),各部分均为可选(方括号含义与命令行可选参数一致):fill/align(< 左对齐、> 右对齐、^ 居中、= 处理符号)、sign、#(加上则保留 0b 前缀,不加则自动去掉)、0(前导补 0)、width(宽度)、type(b 表示二进制)。故 '08b' = 补 0 + 宽 8 + 二进制。
  • 单元测试思路(约 26:20):写好一段就先用 print 打印中间结果对比验证,而不是全部写完再运行。
  • 6 比特分组与字符表(约 28:30):用切片 binary_string[i:i+6] 以 6 为步长滑动分组(沿用上节课作业的"滑动窗口"概念);字符表可用 string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/' 偷懒生成;int(group, 2) 把 6 比特二进制串转回整数作下标取字符。
  • 补尾逻辑(约 32:45):tail_number = len(original) % 3,非零时给 binary string 追加 '00' * (3 - tail_number) 使其被 6 整除,并给结果追加 '=' * (3 - tail_number)。注意必须先判断是否为 0,否则整除时会多补。字符串乘法是 Python 重复字符串的便捷特性。
  • 解码 decode(约 37:50 起):直接复制 encode 反向操作:
  • 用 encoded_message.count('=') 数出填充等号个数(约 39:00,str.count(sub[, start[, end]]),start/end 可选);
  • 去掉等号:方法一 encoded_message.replace('=', ''),方法二切片 encoded_message[:len(encoded_message) - tail_number](约 42:30);
  • 逐字符用 base64_string.index(c) 找下标(约 44:50:find 找不到返回 -1,index 找不到直接 raise ValueError——解码场景故意用 index 让错误尽早暴露,因为出错说明编码就写错了);
  • 用 format(index, '06b') 转 6 比特拼接,再用切片砍掉尾部补的 0(数量为 tail_number * 2);
  • 按 8 比特分组转整数后 byte.to_bytes(1, byteorder='little') 转回单字节拼入结果 bytes(约 51:00;字节序大端/小端:个人电脑都是小端 little-endian,相关知识在《计算机安全与维护》"字节序/文件记录头分析"节约 6 分钟处);
  • 结果变量用 b'' 初始化(bytes 字面量),bytes 不可改内容但可拼接。
  • 测试验证(约 54:00):随机生成 100 组数据循环测试 encode→decode 是否与原始 bytes 一致;Windows 10 下 Win + . 可呼出 emoji 面板打对勾叉号。
  • 方法论总结(约 55:30):画流程图 + print 中间验证 + "小黄鸭调试法"(把代码讲给别人/自己听一遍,老师故意不及时回复也是把小黄鸭的机会留给学生)。

二、数据类型进阶串讲(约 00:57 - 01:13)

  • 本部分对应录播章节"数据类型进阶"与"输入输出",老师认为看一遍视频有概念即可,真正掌握靠后续编程练习。
  • 列表:extend 等价于两个列表相加的拼接;可迭代对象 = 能用 for 循环迭代的对象(字符串、列表、元组、range 等都是)。
  • 元组(重点停下讲)(约 01:04 起):元组不可变,初始化后内容不能改不能删;不打括号的逗号序列本身就是元组——a, b = b, a 交换两变量无需中间变量,本质是元组解包;函数 return a, b 看似返回多个值,实际返回的是一个含两个元素的元组,c, d = func() 是元组解包赋值。
  • 集合 set(约 01:09):用大括号但没有冒号(区别于字典的 key: value),元素不重复,典型用途是**去重**。
  • 使用频率:列表、字典最常用;range 循环时用;元组、集合较少。
  • 答疑插话(约 01:11):Python 没有数组概念,列表就是变长数组(不像 C 语言需预先声明空间)。
  • input 类似 C 语言 scanf;print 默认输出到**标准输出**(上学期终端章节讲过标准输入/输出/错误输出)。
  • print(..., file=f) 可以把内容打印到 open('test.txt', 'w') 打开的文件对象里,与 f.write() 等效。
  • 用途:日志思想(约 01:37):程序规模大时终端一关调试信息就没了;图形界面程序没有黑框框可看 print。最原始的日志就是把 print 写进文件,Python 有专门的 logging 模块(原理上完全可用 print-to-file 实现),建议自行查文档。
  • f-string:f'...{name}...' 是 format 的简写形式,{name} 后加冒号即可套用前面讲的格式规范迷你语言(如 {age:08d})。

四、BMP 转 ASCII 字符画实例(约 01:13 - 01:33)

  • 演示代码 ascii_pic.py:把一张 24 位 BMP(512×512)转成字符画。素材准备:截图后用画图(MSPaint)另存为 24 位 BMP(曾误存成 8 位 256 色 BMP 导致报错——8 比特只能表示 256 色,24 位可表示 2^24 色)。
  • 图像为什么是倒的(约 01:19):BMP 像素数据从最底部一行开始存储,而代码从上往下读,所以图是倒的;想正过来可从底部开始读或旋转。借此讲解 BMP 文件结构:文件头(存大小、宽度等元信息)+ 位图信息头 + (可能有调色板)+ 位图数据(每个像素的 RGB 值)。
  • 灰度映射(约 01:22):每个像素保存 RGB(红绿蓝)三个值,用图像处理的固定公式(gray = R×系数 + G×系数 + B×系数)算出 0-255 灰度,再映射到约 70 个不同灰度的字符上($ 最黑,空格最白),与 base64"算下标取字符"思路类似。
  • 失真与优化(约 01:25):1 像素对应 1 字符导致画面放大且编辑器字体是长条形导致比例失真;优化思路:把图片切成 8×8(或更大)的块,取块内平均灰度对应一个字符;或换正方形等宽字体。
  • 引入的意义(约 01:29):一是练习读文件/分析文件,二是引入安全领域的文件格式拆解概念——逆向工程、软件安全、CTF 图像题/逆向题的基本功就是分析二进制文件的格式结构,与上半学期分析文件系统结构一脉相承。熟悉格式不是背下来,而是知道"有这么个东西"、会查文档分析。

五、文件读写与各类文件格式库(约 01:42 - 02:11)

  • seek 与 tell(约 01:41):文件对象内部有位置指针,每次 read 后指针后移;seek 可在不读的情况下移动指针,tell 返回当前指针位置。
  • 官方文档是宝藏(约 01:43):本课无教材是因为官方文档比教材新、全,还有中文版。标准库支持 HTML、XML、csv 等文件格式。
  • 压缩包(约 01:44):需求引子——200 个压缩包批量解压。tarfile 文档有现成示例:tarfile.open('sample.tar.gz') → extractall() → close();zipfile 的 extractall 文档没给示例(课堂小翻车),但用法类似,遍历压缩包写循环即可。
  • Excel:推荐 openpyxl(约 01:50),能读写 xlsx、处理格式、样式、合并单元格,文档示例简洁。
  • PDF:Adobe 闭源,开源好用的库不多,凑合可用,以库名 + documentation 为关键词搜索。
  • Word:python-docx(约 01:53)可提取 docx 中的表格、图片等。应用场景:老师派活把 200 个 Word 文档里的表格数据统计到 Excel——python-docx 读 + openpyxl 写,手工一周的活写代码三天跑一天搞定,"懒是第一生产力"。
  • 图像:OpenCV(裁剪、缩放、降噪、磨皮,可做美颜软件);Pillow 更低阶,Image.open('demo.png').save('demo.bmp') 两行搞定格式转换(约 01:57,演示用 pip 安装、从 PIL 导入;PIL = Python Imaging Library,老库停更后由 Pillow 继承,故名)。
  • 音频(约 02:00):PortAudio(C++ 跨平台音频库)有 Python 绑定 PyAudio;演示了一个 GitHub 开源变调项目——用内置库 wave 读音频 + numpy 做傅里叶变换到频域,把频率提高 1.25/1.5 倍,男声变"女声"(男声频率低、女声频率高)。
  • 视频:没有特别好的现成库,FFmpeg 是命令行工具(可用 Python 调命令行间接调用),其官方库叫 libav(audio + video)。

示例与演示

  1. base64 encode/decode 现场编码(live.py):从流程图出发,先解决"bytes 迭代出 int → bin/format 转定长二进制串",再处理补 0 补等号边界条件,最后复制 encode 改写 decode;用随机 100 组 bytes 做循环回归测试。作业要求即此,不会就画流程图。
  2. BMP 转 ASCII 字符画:准备 24 位 512×512 BMP,读文件头与像素,RGB 算灰度映射 70 级灰度字符输出到文本;指出倒图原因、比例失真原因及分块平均优化方向(可作为自愿的小练习,不布置成作业)。
  3. print 写文件演示:f = open('test.txt', 'w'); print('abc', file=f); f.close() 与 f.write('abc') 等效。
  4. tarfile 解压演示:文档示例三行解压 tar.gz。
  5. Pillow 格式转换演示:pip install pillow,from PIL import Image,Image.open('demo.png').save('demo.bmp')。
  6. 音频变调演示:播放开源项目效果(周杰伦歌曲变调为"女声"),解释频率平移原理。

重点与难点

  • base64 的边界条件:补 0 个数 = '00' * (3 - len%3),等号个数同理;必须先判断余数非 0,否则整除时会多补。解码时砍尾巴是 tail_number * 2 个 0。
  • bin() 省略前导 0、带 0b 前缀,直接用会错位;format(x, '08b') 才是正解(查文档要顺着文档往下读,文档会告诉你 format 的存在)。
  • bytes 迭代直接得到 int,不用再 ord;bytes 不可变但可拼接。
  • find 返回 -1 与 index 抛异常的取舍:该报错的地方就让它报错,能尽早暴露上游错误。
  • 元组无括号写法与函数"返回多值"的本质是元组,是 Python 高频灵活写法,见到不要惊讶。
  • print 写文件背后的日志思想,比语法本身更重要。
  • 各类文件格式库不需要记用法,需要记住"有这个东西、去哪里查文档"。

关联内容

  • 承接上节课/上次作业:ord/hex 转换、滑动窗口切片分组、string 库、random.randbytes。
  • 对应录播章节"数据类型进阶""输入输出(文件读写)",下节课讲"文件与目录"。
  • 字节序(大端/小端)复习自《计算机安全与维护》课程;BMP 文件结构分析、逆向/CTF 的文件格式分析思想与上学期文件系统结构分析呼应。
  • BMP 拆解在"文件与目录"章节的练习视频中有更详细讲解。
  • 后续章节(Web、爬虫、可视化)会大量使用本节提到的第三方库;Excel/Word 处理与学习委员统计成绩等日常场景直接相关。