Base64编码的作用

将任意的二进制比特串编码成由ASCii码中的64个可显示字符组成的字符串。

为什么需要base64编码?

所有的文件,本质上都是0、1组成的比特串,文本文件、二进制文件的区别只在于操作系统如何解读文件内容。前端最常用的html、css、js都是文本文件,而文本文件的所有比特都会被操作系统当做字符编码来解读(比如按照UTF-8编码规则来解读),所以,当我们想在一个文本文件里保存二进制文件的数据(比如在css文件里保存一张图片)时,就会遇到麻烦——比如,操作系统会强行把原本属于图片的二进制数据当成UTF-8编码串来解码,然后我们会在页面上得到一堆不知所云的乱码,甚至可能会破坏真正的文本数据区域。

当然,这个问题是有解的——我们用可显示的ASCii字符来编码二进制数据,然后保存在css等文本文件里,在真正使用到这些数据时(比如<img>标签渲染图片内容)再进行解码。这就是base64所做的事。

在浏览器环境下,我们有widow.btoawindow.atob两个全局方法,分别用于对数据进行base64编解码,其中a代表ASCii,b代表binary,知道了这个含义就不会把两个方法记反啦。

为什么码表里有64个字符?

因为ASCii码的可见字符只有95个,向下取整(2的n次方)就是64。

具体是哪64个?A-Z、a-z、0-9,以及+、/ 这两个符号。26+26+10+2正好是64。

除此之外,还有一个字符有时也会作为占位符出现在Base64编码串的末尾,即等号 = 。一个等号表示编码时在原比特串的末尾补了2bit的0。等号只可能出现1或2个,下面会解释为什么。

为什么base64编码后文件体积会变大?

在64个字符的码表里,一个字符可以表示6bit的数据(2^6=64),而这样一个ASCii码字符要占一个字节(1byte = 8bit),也就是说,base64编码其实是用8个比特来表示原二进制串里的6个比特,所以编码后体积是原二进制串的4/3。

正是因为这个原因,前端base64编码只适用于小文件,因为增加的体积不多,还可以省下一次网络请求;但当文件体积比较大时,会影响网站初次加载和渲染的速度(解码base64大文件也会消耗性能),这种时候文件还是放CDN比较好。

为什么base64补0只有两种情况?

考虑另一个限制条件:在操作系统中,文件系统进行读写操作,都是以字节为单位来操作的,而一个字节等于8bit,因此,base64的编码对象,其二进制位数都是8的倍数,而base64编码是每次从中取出6bit来编码,这就可能在二进制串的末尾出现除不尽的情况——有且仅有两种情况:

1. 剩1个字节待编码,从中取出6bit之后,剩2bit尚未编码(8 - 6 = 2),这时需要补4位0。

2. 剩2个字节待编码,从中取出12bit之后,剩4bit尚未编码(8*2 - 6*2 = 4),这时需要补2位0。

剩3个字节时,正好对应4个6bit,不需要补0。

所以我们可能在Base64串尾部看到1或2个等号,就是这样来的。

Base64与URI编码的异同

相同点它们都是用给定的字符集去表示更广范围数据的方法。

区别:URI编码是针对超出URI合法字符集(是ASCii可显示字符集的子集,去掉了不安全字符和保留字符)范围外的字符做编码,而base64是针对二进制数据做编码——一个是对文本的编码,一个是对二进制数据的编码。

两个Tips

1. 文本本质上也是二进制数据,因此也可以强行拿来做base64编码

2. base64编码中的斜杠号/和等号=不属于URI合法字符,故base64编码串不能直接带在链接参数上

最新文章

  1. Hibernate映射多对多双向关联关系(小案例)
  2. knockout的依赖属性dependentObservable的参数 和Value转换器
  3. mongodb的固定集合(优化效率)
  4. C# 获取随机可用端口号
  5. spring-security 登陆认证之初次探究
  6. How to resolve the SQL error “cannot connect to WMI provider”
  7. 拷贝构造函数,深拷贝,大约delete和default相关业务,explicit,给定初始类,构造函数和析构函数,成员函数和内联函数,关于记忆储存,默认参数,静态功能和正常功能,const功能,朋友
  8. Oracle随机获取记录
  9. java OJ题目判断输入结束(与C语言的EOF结束等价)
  10. Android开发——签名包的生成
  11. OpenCV空洞填充算法
  12. Web前端2019面试总结
  13. Git + Docker + Jenkins自动化部署web到Linux(Centos)
  14. 用JAVA写一个简单的英文加密器
  15. lsof详解
  16. jdk1.8 HashMap红黑树操作详解-putTreeVal()
  17. shiro授权及自定义realm授权(七)
  18. 记录Ubuntu 16.04 安装Docker CE
  19. CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
  20. could not execute menu item系统找不到指定的文件

热门文章

  1. 【RN - 基础】之React Native常见问题及解决方案
  2. 【数据结构】之队列(C语言描述)
  3. Zookeeper 应用实现-配置中心
  4. Python实现简单框架及三大框架对比
  5. MySQL主从介绍、配置主从、测试主从同步
  6. 小白的springboot之路(二)、集成swagger
  7. uni-app之网络请求
  8. Erlang/Elixir精选-第2期(20191209)
  9. 转:org.apache.maven.archiver.MavenArchiver.getManifest错误
  10. nginx反向代理 和部分优化