大家好,湿兄又来吹牛逼了 因为最近需要将任意格式、任意大小的文件进行 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 算法:
注意事项:
防止有的同学没看明白,这里用猿湿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 编码的时候,需要注意两点:
对文件进行 Base64 解码
忽然就懒了,不想写对 Base64 进行解码的时候需要注意什么了,大家自己研究研究吧。提个醒,「怎么来的,就怎么回去」。
我已经用Python实现了一个完整的包含文件与 Base64 之间正反编码的脚本,需要的同学后台回复「 base64 」获取。
写在最后
大家可以看得出来,这篇文章了里的例子,是湿兄「一个bit一个bit」打出来的。关注分享点赞留言,还不来个一条龙嘛?
想到最近的「洗稿」实锤,我就想说一句,谁要是有耐心把我这篇洗了,那你就标原创吧~
哈哈。