Base64 编码及其实现
Base64是一种基于64个可打印字符来表示二进制数据的方法。
当我们用文本编辑器打开 jpg、pdf、exe这些文件格式的时候,会看到一大堆的乱码,这是因为二进制文件包含很多无法显示和打印的字符。所以,如果想要让记事本这样的文本编辑器处理二进制数据,就需要一个从二进制到字符串的转换方法。Base64就是一种最常见的二进制编码方法。
原理
文本文件和二进制文件
使用计算机时,我们会遇到各种各样的文件格式,有像 txt、cpp、java、md这样的可以用文本编辑器直接打开的文件格式,我们称之为 文本文件,也有一些文件用编辑器打开时是一堆乱码,比如像上面提到的 jpg、wav、pdf,这些文件格式称之为 二进制文件。
我们知道,所有文件在计算机的存储都是一堆0和1的序列,也就是说不论是文本文件还是二进制文件,在物理上,计算机的存储是都是二进制的。 所谓的文本文件和二进制文件的区别并不是物理上的,而是逻辑上的。广义上来说,文本文件也是二进制文件。二者的区别是因为你看待数据的方式不同而产生的差别,具体的说二者的区别就在于打开这个文件的程序对其内容的解释上。
以文件的读写过程为例,这实际包含了如下的两个转换过程
磁盘 ----> 文件缓冲区 ----> 应用程序内存空间
第一个过程中,文件被应用程序从磁盘读取到文件缓冲区,二者都是一堆的0和1的序列,这个时候文本文件和二进制文件并没有什么区别。
接下来,不同的应用程序,根据面对的不同文件格式,对一堆的0和1序列进行解释。对于文本文件,应用程序直接将其中的数据(也就是这一堆0和1序列按照ASCII或者Unicode编码的方式解释出来),显示成文本的形式。对于其他类型的文件,一般包括了控制信息和内容信息,应用程序按照文件格式,从这些数据中解析出对应的数据内容,比如常见的wav文件解析过程,而这些就是所谓的二进制文件。
Base64的转换
Base64编码选择的64个可打印字符为字母A-Z,a-z、数字0-9,这样共有62个字符,此外还有两个字符在不同的系统中而不同。比如对于MIME格式,其采用的为
|
|
然后,而二进制数据进行处理,每3个字节一组,一共是 $ 3 × 8 = 24 $ bit,划分为4组,每组正好6个bit。
这样,我们得到4个数字作为索引,然后查表,获得相应的4个字符,就得到编码后的字符串。所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。
如果要编码的二进制数据不是3的倍数,Base64就会在后面补0,每补1个0就在编码出来的字符串后加上1个 = ,解码的时候会自动将 = 去掉。
Python中内置的 base64可以直接进行base64的编解码
|
|
C++实现
此处源码可在 base64的C++实现
encode方法
- 首先计算生成base64字符串的长度
- 原来的二进制流中,每3个字节为整体,合为一个32位的bit串
- 将这个32位bit串的低24bit的每6个比特作为索引,得到映射表中对应的字符
- 如果原来的字节串不是3的倍数,则补零,并且每补一个0加一个 =
|
|
decode方法
- 首先判断base64字符串的长度是不是4的倍数
- 去除
=这样的 pad,=只可能是1个或2个 - 遍历整个base64字符串,每4个为一个单位(对应也就是3个字节的二进制数,以value表示),对于每个字符得到其在映射表中的索引,从而得到value的值,进而解析出每个字节的值
对应代码如下
|
|
调用
写一个简单的demo验证
|
|
编译后得到
|
|
应用
上面说了base64的编码方法,那么为什么要使用base64编码呢,有哪些情景需求?
我们知道在计算机中任何数据都是按ascii码存储的,而ascii码的128~255之间的值是不可见字符。而在网络上交换数据时,比如说从A地传到B地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据先做一个Base64编码,统统变成可见字符,这样出错的可能性就大降低了。
HTML内嵌base64编码图片
MIME
X.509 公钥证书
-
No backlinks found.