MENU

理解 Base64 及 Quoted-printable 编码

June 13, 2018 • Code

前言:学习 Base64 及 Quoted-printable 编码。

Base64 编码与 Quoted-printable 编码都是一种「应用编码」,它与 之前文章 中的计算机编码方式有本质的区别:计算机内部编码解决的是 01 序列的定义表示问题,Base64 及 Quoted-printable 编码解决的是二进制的传输问题

举个栗子:邮寄一把可组装的椅子。发件人与收件人明白这是一把椅子,而非桌子,靠的是常识判断,将椅子的概念与实物对应的映射关系类比计算机内部编码,而如何把椅子拆开及组装的方法可类比 Base64 等编码。

Base64

Base64 概念

来自维基:

Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。 完整的 Base64 定义可见 RFC 1421RFC 2045。编码后的数据比原始数据略长,为原来的 \({\displaystyle {\frac {4}{3}}} \)。在电子邮件中,根据 RFC 822 规定,每 76 个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的 135.1%。

简单来说,Base64 的思想是用一个有限字符集合表示二进制数据

在 Base64 中的可打印字符包括字母 A-Za-z、数字 0-9,这样共有 62 个字符,此外两个可打印符号在不同的系统中而不同。除此之外,等号 = 用来作为后缀用途,所以实际编码字符共 65 个。

在 MIME 格式的电子邮件中,另外两个字符为加号 + 和斜杠 /,URL 编码中使用 -_ 替代规范中的 +/,同时 = 可以省略。

Base64 编码规则

Base64 索引表(以 MIME 为例)

具体编码方式

  1. 依次从二进制数据中取 3 字节长度的数据放入缓冲区,共 24 bit。数据不足3字节时,在缓冲区用 0 补足 24 位。

  2. 每次从缓冲中取出 6 bit,将二制数转为十进制并在索引表中查找字符输出,直到全部输入数据转换完成。

若原数据长度不是 3 的倍数时且剩下 1 个输入数据,则在编码结果后加 2 个 =;若剩下 2 个输入数据,则在编码结果后加1个 =

举个栗子:

扩展

  • Java 中如果需要使用 Base64,可使用 Java8 里 java.util.Base64 以及 Java6 的 javax.xml.bind.DatatypeConverter

  • 在线 Base64 编码解码工具

Quoted-printable

来自维基:

Quoted-printable 是使用可打印的 ASCII 字符(如字母、数字与"=")表示各种编码格式下的字符,以便能在 7-bit 数据通路上传输 8-bit 数据, 或者更一般地说在非 8-bit clean 媒体上正确处理数据。

Quoted-printable 这一种编码规则优点在于 ASCII 字符编码过后不变。换句话说,如果文档中 ASCII 字符很多,并含有少量非 ASCII 字符及二进制数据,那用 Quoted-printable 编码后的文本可读性好且结构紧凑,因为大量的 ASCII 字符并没有被改变。相反,如果文档含有大量非 ASCII 字符及二进制数据,那编码过后的文本将变得既不可读又非常低效。Base64 编码后的文档不可读,但好处在于编码成本均衡。所以编码包含大量 ASCII 字符文档适用 Quoted-printable,编码非 ASCII 字符及二进制数据适用 Base64。

「不可读」指人难以读懂。

编码规则

  • 可打印字符

所有可打印 ASCII 字符(十进制值的范围为 33 到 126)可用ASCII字符编码来直接表示,等号 = 除外(十进制值为 61)。

  • 水平制表符与空格

ASCII 的水平制表符(十进制值为 9)与空格符(十进制值为 32)如果不出现在行尾则可以用其 ASCII 字符编码直接表示。如果这两个字符出现在行尾,必须 QP 编码表示为 =09 (tab)或 =20(space)。

  • 其它所有字符

除了上面提到的几种情况,Quoted-printable 针对其它所有字符有如下规定:任何8-bit 字节值可编码为 3 个字符:一个等号 = 后跟随两个十六进制数字(0–9 或 A–F)表示该字节的数值。例如,ASCII 码换页符(十进制值为 12)表示为 =0C,等号 =(十进制值为 61)表示为 =3D

  • 行结束标志

如果数据中包含有意义的行结束标志,必须转换为 ASCII 回车(CR)换行(LF)序列,既不能用原来的 ASCII 字符也不能用 QP 编码的 = 转义字符序列。 相反,如果字节值 13 与 10 有其它的不是行结束的含义,它们编码为 =0D=0A

quoted-printable 编码的数据的每行长度不能超过 76 个字符。为满足此要求又不改变被编码文本,在 QP 编码结果的每行末尾加上软换行(soft line break)。即在每行末尾加上一个 =,但并不会出现在解码得到的文本中。这种软换行也适用于文本的行非常长,超过了软件限制(例如,某些 SMTP 软件要求最大行长为 1000 个字符),这也是 RFC 2821 允许的。

栗子

To be, or not to be,
that is a question.

对应 QP 编码:
To be, or not to be,=0Athat is a question.

参考

Last Modified: July 5, 2018
Archives QR Code
QR Code for this page
Tipping QR Code