跳转至

5.6 程序结构——作业 Base64

内容梗概

本课讲解本次作业的背景知识——Base64 编码,它是上一次作业(可打印字符转换)的进阶版。老师从 Base64 的历史由来(SMTP 电子邮件协议只能传可打印文本,MIME 补充规范用 Base64 把二进制附件转成可打印文本)讲起,详细拆解了编码算法:选 64 个可打印字符、每 3 字节(24 比特)重新按 6 比特分组、以 6 比特值作下标查表输出,以及不能整除时补零并在末尾加 = 的规则。课上还演示了 Python 内置 base64 库的 b64encode 用法(输入必须是 bytes 类型),作业要求自己写程序模拟这个算法过程。注:本段字幕在讲解补 = 规则后戛然而止,作业的具体提交要求未完整录入。

知识点详解

Base64 的由来

  • Base64 是随着 SMTP(电子邮件协议,用于发邮件;对应的 IMAP 用于收邮件)之后的补充规范 MIME 发明的一种编码方式 (约 00:31–01:54)。
  • 早期电子邮件只考虑正文文本:全部是**可打印字符**(能 print 显示出来的字符串),甚至只考虑英文和数字。
  • 现代邮件有附件(图片、zip、甚至 exe),它们是 10011001… 的**二进制文件**,其中含大量**不可打印字符**——如 0x00(C 语言里字符串的结束符),在命令行/记事本里显示不出来。只支持可打印文本的邮件系统发不了这些东西。
  • 解决办法(MIME):把二进制文件统一转化成可打印文本再传输,这套统一规则就是 Base64。二进制→可打印文本叫**编码(encode),反过来叫**解码(decode)。

Base64 的编码算法

  • 选取 64 个可打印符号:大写 A–Z(26)+ 小写 a–z(26)+ 数字 0–9(10)+ + 和 /,共 64 个 (约 01:58)。
  • 编码过程(以单词 "Man" 为例,约 07:33–09:51):
  • 每个字符转 ASCII 数字:M=77、a=97、n=110;每个字符 1 字节 = 8 比特。
  • 每 3 个字节为一组,共 24 比特。
  • 把 24 比特**重新按 6 比特分组**,正好分成 4 组(24 是 6 的整数倍)。
  • 6 比特可表示 0–63(2^6=64),正好作为长度 64 的字符表**下标**;把每组 6 比特换算成索引,去字符表中取出对应字符,按顺序输出即得 Base64 编码结果。
  • 不能整除(补零与 = 填充) (约 10:04–18:00):
  • 字节数不是 3 的整数倍时,缺的部分全部补 0 比特参与分组,末尾再加等号 = 补齐。
  • 规则:模 3 余 2(如 5 字节)→ 末尾加 1 个 =;模 3 余 1 → 末尾加 2 个 =。
  • 所以 Base64 编码结果常常以 = 或 == 结尾。
  • 老师画图演示:只剩 1 个字符(M)时,其余位置全当 0,能分出的组照常换算输出字符,剩余组用 = 占位补完整。

Python 内置 base64 库演示

  • import base64,调用 base64.b64encode(...) 即可完成编码 (约 10:47)。
  • 注意:b64encode 的参数必须是 bytes 类型(bytes-like,二进制数据),不能直接传字符串。写法:在字符串引号前加 b,如 b"Man\x00..."。bytes 里的值可以是任何字节,包括不可打印的 0d、00 等(二进制数据类型后续课程才正式讲,这里先强行使用)(约 11:09–13:34)。
  • 小测验:示例二进制数据共 5 个字节(注意不可打印字符也各占 1 个字节),5 不能被 3 整除(模 3 余 2),编码结果末尾加 1 个 =。

示例与演示

  • 用 "Man" 手算 Base64:M/a/n → 77/97/110 → 24 比特 → 重新按 6 比特分 4 组 → 每组作下标查 64 字符表输出。
  • base64.b64encode(b"...") 现场演示编码结果,观察末尾 = 的个数与字节数模 3 的关系。
  • 画图演示 5 字节、1 字节等不能整除情形下的补零与补等号过程。

作业要求与解题思路

  • 作业定位:上一次作业(可打印字符转换)的进阶版——自己写程序实现 Base64 编码,模拟这个算法的过程(“比较硬核”,不直接用内置库交差)。
  • 解题思路(依课堂讲解):
  • 输入二进制/字符串数据,把每个字节转成 8 位二进制;
  • 每 3 字节(24 比特)一组,重新按 6 比特切成 4 段;
  • 每段换算成 0–63 的索引,在 64 字符表(A–Z、a–z、0–9、+、/)中查表取字符;
  • 字节数模 3 余 2 补 1 个 =、余 1 补 2 个 =(缺位按 0 比特处理)。
  • 可用内置 base64.b64encode 验证自己程序的结果是否正确。
  • 注意:字幕文件在补 = 规则讲完后即结束,作业的具体提交方式、截止时间等未在字幕中出现。

重点与难点

  • 理解 Base64 存在的意义:邮件系统只支持可打印文本,二进制附件必须编码后才能传输。
  • 核心算法就两步:3 字节变 24 比特、24 比特按 6 比特重分成 4 组查表;6 比特对应 2^6=64 所以叫 Base64。
  • 补零与补 = 是最容易出错的地方:先补 0 比特凑组,再在结果末尾按余数补 =;不可打印字符(如 0x00)也是完整的一个字节,计字节数时不能漏。
  • b64encode 只接受 bytes 类型,字符串前要加 b 前缀。

关联内容

  • 本次作业是上一次作业(字符串/可打印字符转换)的进阶,继续锻炼循环、切片、取模等基本功(对应 5.3 循环语句中点评的“两字符一组”解法)。
  • 涉及的前置知识:ASCII 码(5.1 字符串比较时用过)、二进制与比特(C 语言基础)、bytes 类型(后续课程正式讲)。
  • 与 5.5 闲聊 HTTPS 同属网络应用话题:SMTP/IMAP 邮件协议、MIME 规范在后续《计算机网络》课会正式学习;实践部分还会讲用 Python 发邮件(呼应 5.3 的“给尾号为 5 的学号发邮件”例子)。