前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个bit一个bit的进行 Base64 白话科普,看不懂算你输

一个bit一个bit的进行 Base64 白话科普,看不懂算你输

作者头像
菜天哥哥
发布2018-07-03 12:28:26
8910
发布2018-07-03 12:28:26
举报
文章被收录于专栏:猿湿Xoong猿湿Xoong

大家好,湿兄又来吹牛逼了 因为最近需要将任意格式、任意大小的文件进行 Base64 编码存储,所以把 Base64 编解码撸一遍。 总是先有需求,再有市场嘛~

写在前面

首先,让人放心的是,Base64 没什么难的。

其次,让人放心的是,看完 Base64 编解码算法后,实现任意文件编解码也没啥难的。

所以,你输的可能性不大~

Base64 是什么?

一种「编码方式」。

一种用「可读字符」来表示「二进制数据」的编码方式。

对比使用一下平时将exe文件用记事本打开的骚操作,你就明白啥叫可读字符了。Six不Six?

使用 Base64,你可以将任意数据或文件以「可读字符形式发送或存储」。参考维基百科可以看到这一段:

Base64是一种基于64个可打印字符来表示二进制数据的表示方法

所以Base64为什么叫Base64而不是叫Base32、Base100,是因为它是用64个可打印字符来表示二进制数据的。

通常,会有人误认为 Base64 是一种加密方式,这是错误的。虽然进行 Base64 编码后的数据会显得杂乱无章、看不出原数据,但是对于带有恶意的人,Base64 无法阻止他们的恶意。所以想加密,还请用正了八经的加密算法。

Base64 编解码算法

Base64 的算法可以说是「按图索骥」。

这个表划重点,后面要考 表示范围: A-Z,a-z,0-9,+,/ 全部内容:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

讲之前,咱们要知道:1Byte(字节) = 8bit(比特)。好,开始。

Base64 算法:

  1. 以原数据中每 6 个 bit 作为一个单位,在取出的 6bit 前方填充 2bit 的 0 后,变为 8bit,也就是一字节。设最后剩余bit数为 t (t <= 6),则补充的 bit 0 个数为 8 - t 个。
  2. 将每个填充过 bit 0 的单位转化为对应数字。每个数字值的范围为 0 - 63(2的6次方 - 1 = 00111111)。
  3. 将数字作为下标,在表中查找其对应表示的字符。

注意事项:

  1. 用 Base64 的方法取数据(每次取6bit),那么想取“完整字节数”,最少需要4次,因为 6 和 8 的最小公倍数是 24,也就是 3 字节 == 4个 Base64 单位。
  2. 对于不足 3 的倍数字节的原数据,作以下处理:
    1. 余数为 2,也就是差了一个字节,则在最后结果补一个「 = 」
    2. 余数为 1,则在最后的结果补两个「 = 」

防止有的同学没看明白,这里用猿湿Xoong的「Xoong」作为原数据,给大家展示下 Base64 的编码过程。

原数据:

Xoong 5字节

ASCII 编码后的二进制数据为:

X -> 01011000 o -> 01101111 o -> 01101111 n -> 01101110 g -> 01100111

Base64 编码过程(每次取6bit)

原数据以 6bit 为单位分解 010110 000110 111101 101111 011011 100110 0111 编码后,共7个字节,前方加粗的 bit 0 是填充的 00010110 00000110 00111101 00101111 00011011 00100110 00000111 对应数字为 22 6 61 47 27 38 7

下列为「Xoong」最终的 Base64 encode 后的数据。因为「原数据」缺少了 1 个字节才到 6 字节,所以加了个「 = 」

对应最开头划重点的表中字符,结果为 WG9vbmc=

细心的同学会发现,编码后的数据长度变长了。是的,基于算法特性,经过 Base64 编码的数据长度会增加 1/3,也就是原来的 4/3 倍(6bit 变 8bit 嘛)。

简单吧,没骗你们吧?

对文件进行 Base64 编码

什么?有人说我上一节没讲解码?你们把编码流程倒过去就是解码了,完全可逆。

对于文件的读,我们永远不能忽视一个客观事实:文件的size有时比内存总量还大。

100G 的文件对 8G 的内存

这时就会存在:直接读取大文件的全部数据将会导致系统 OOM。有经验的同学一定会边坐着小板凳边嗑着瓜子的说:“分段读取不就行了?”,大佬,大佬!这位同学说的连一个标点符号都没错,「分段读取」。

但是,BUT

分段读取之后,就会面临着分段进行 Base64 编码的情况。由于 Base64 算法的第一点,如果不注意每次分段读取的数据量,就会导致数据失真。

还以上面的“Xoong”为例,假设A文件存储此字符串,程序分别以每次1、2、3个字节读取,并最后存储在B文件中。看看最终的到的结果。

每次读取1字节

X 010110 00 编码后 00010110 00000000 结果 WA== 其余字符:o -> bw==, n -> bg==, g - > Zw==


依次写入文件B,最终文件B数据:WA==bw==bw==bg==Zw==,对比正确数据:WG9vbmc=,失真

每次读取2字节

Xo 010110 000110 1111 编码后 00010110 00000110 00001111 结果 WG8= 其余字符:on -> b24=, g -> Zw==


依次写入文件B,最终文件B数据:WG8=b24=Zw==,对比正确数据:WG9vbmc=,失真

每次读取3字节

Xoo 010110 000110 111101 101111 编码后,无冗余bit 00010110 00000110 00111101 00101111 结果 WG9 其余字符:ng -> vbmc=


依次写入文件B,最终文件B数据:WG9vbmc=,对比正确数据:WG9vbmc=,正确

上面的过程证明了:如果不是以「3的倍数字节」进行文件数据分段读取,将会造成「数据失真」。

综上,我们在对文件进行 Base64 编码的时候,需要注意两点:

  1. 进行分段读取
  2. 每次读取3的倍数个字节的数据,如 3 * 1024

对文件进行 Base64 解码

忽然就懒了,不想写对 Base64 进行解码的时候需要注意什么了,大家自己研究研究吧。提个醒,「怎么来的,就怎么回去」。

我已经用Python实现了一个完整的包含文件与 Base64 之间正反编码的脚本,需要的同学后台回复「 base64 」获取。

写在最后

大家可以看得出来,这篇文章了里的例子,是湿兄「一个bit一个bit」打出来的。关注分享点赞留言,还不来个一条龙嘛?

想到最近的「洗稿」实锤,我就想说一句,谁要是有耐心把我这篇洗了,那你就标原创吧~

哈哈。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 菜天 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档