Base64编码是一种将字节数据编码为字符串的编码,字节数据会被编码成由64个可打印ASCII字符组成的字符串,这64个字符包括大写字母A-Z, 小写字母a-z, 以及数字 0 -9再加上 + 和 / ,刚好64个字符。对应的字符表如下图:

base64编码的一个用途就是对http的头信息进行编码,由于http头信息使用ASCII编码,如果包含特殊字符可能会导致头信息解析异常,采用base64编码保证头信息只包含一些简单字符,提高了安全性。前端在显示图片元素时也经常会遇到base64编码的图片资源。

那么base64具体是如何进行编码的呢?

编码方式很简单,就是对目标字节中的每六个bit位表示为字母表中的某个字符,例如:

‘abc’对应的二进制字节为: 01100001 , 01100010 , 01100011 ; 每六位进行分组得到的结果如下:

011000, 010110, 001001, 100011,转化为10进制就是:24,22, 9, 35,根据上面的字母表得到各个数字对应的字符为:YWJj,所以abc最终会被编码为 ‘YWJj’。由于三个字节最终被编码成了四个字节的字符串,所以长度增加了1/3.

看着这里大家可能会有一个问题,假设原数据的字节长度不是3的倍数,就会有剩余的bit位不够6个字符,这是就会涉及到填充的问题,填充就是在原数据后面加上额外的冗余位,使数据的bit位长度刚好能被24(也就是3个字节)整除(6和8的最小公倍数)。具体的填充规则可以简单的表述为: 任何完全填充(不包含原始数据中的位) 的 6 位组都由特殊的第 65 个符号“=” 表示。 如果 6 位组是部分填充的, 就将填充位设置为 0(http权威指南)。

举个例子:假设在编码的过程中原数组有四个字节,这时就需要再填充2个字节。假设最后的两个bit为是10,填充后的数据的最后几位如下:

10 xxxx, xxxxxx,xxxxxx (x代表填充位)

根据前面描述的填充规则:第一个6位组对应的数字为 10 0000,后面两个由于时完全填充的,被编码为==,最终的结果的后三位就变成了‘g==’。

在浏览器端,可以调用全局的方法 atob 和 btoa 实现二进制字符与base64编码的字符之间的互相转化。下面给出一个base64编码前端实现的简单例子:

const table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';// 参数为待编码的字符串async function toBase64(str) {const blob = new Blob([str], { type: 'text/plain' });// 获取字节长度,也可以使用第三方库提供的同步方法// 这里为了演示简单const srcBuf = await blob.arrayBuffer();// 获取原数据的字节长度const length = blob.size;// 计算需要填充的位数const padLen = length % 3 === 1? 2: length % 3 === 2 ? 1 : 0;// 最终的长度const size = length + padLen;const arrBuf = new ArrayBuffer(size);const srcArray = new Uint8Array(srcBuf);const dstArray = new Uint8Array(arrBuf);for (let i = 0; i < size; i++) {if (i < length) {dstArray[i] = srcArray[i];} else {dstArray[i] = 0x00;}}let result = [];// 每次处理3个字节for (let i = 0; i < size; i += 3) {// 取出三个字节const a = dstArray[i];const b = dstArray[i + 1];const c = dstArray[i + 2];// 最后一组const isLast = i + 3 > length;console.log(padLen)result.push(a >> 2); // 第一个字节的前6位result.push(((a & 0b00000011) << 4) | (b >> 4)); // 第一个字节的后两位加上第二个字节的前四位// 第二个字节的后四位加上的三个字节的前两位if (!isLast || padLen === 0) {result.push(((b & 0b00001111) << 2) | (c >> 6));result.push(c & 0b00111111); // 第三个字节的后六位} else {if (padLen === 2) {result.push('=', '=');} else if (padLen === 1) {result.push(((b & 0b00001111) << 2) | (c >> 6), '=');}}}result = result.map(code => code === '=' ? '=' :        table[code]).join('');return result;}

base64转二进制字节原理类似,有兴趣的童鞋可以自行尝试!!

实际的运行效果如下图:

讲字节数组转化为base64_Base64编码简介及简单实现相关推荐

  1. java字节数组转换成16进制_Java 将字节数组转化为16进制的多种方案

    很多时候我们需要将字节数组转化为16进制字符串来保存,尤其在很多加密的场景中,例如保存密钥等.因为字节数组,除了写入文件或者以二进制的形式写入数据库以外,无法直接转为为字符串,因为字符串结尾有\0,当 ...

  2. IO知识点整理(序列化,管道流,数据流,字节数组流,与编码)

    一:序列化的问题 1.序列号的使用问题 关于在序列化中的序列号的使用问题,一般要是使用. 因为,每次要序列化的类产生都会产生一个一个新的序列号,如果将这个类的程序修改后,就会产生新的序列号,以前序列化 ...

  3. java io流学设置编码_Java学习日志(21-2-IO流-基本数据类型与字节数组对象与、编码解码)...

    操作基本数据类型的流对象DataStream /* 可以用于操作基本数据类型数据的流对象 */ import java.io.*; class DataStreamDemo{ public stati ...

  4. java二进制 字节数组 字符 十六进制 BCD编码转换

    // 整数到字节数组转换 public static byte[] int2bytes(int n) { byte[] ab = new byte[4]; ab[0] = (byte) (0xff & ...

  5. python2.7下面字节数组(ByteArray)和16进制字符串(HexString)转化

    由于是python2.7 严谨起见,文中不使用字符串的说法,下面只使用str或者unicode的说法 之所以有这个需要,是因为: Hmac-sha1加密在网上计算的结果是HexString,也就是16 ...

  6. java中bitconverter_【Java】BitConverter(数字转字节数组工具类)

    import java.nio.ByteOrder; import java.nio.charset.Charset; /** * 数字转字节数组工具类 */ public class BitConv ...

  7. Javascript 字节数组与Number类型的转化

    自从Node的兴起与火热, Javascript再次成为一门流行语言. 不仅能在浏览器的Web端使用, 还可以向Java\C++等语言一样运行在服务器端(Nodejs) 既然Javascript如此的 ...

  8. Java将字节数组转换成字符串

    reference:http://blog.csdn.net/lmj623565791/article/details/23609929 项目要求把通过TCP传过来的原始报文做保存,所以要先把字节数组 ...

  9. 字符编码简介 ANSI Unicode Unicode big endian UTF-8

    1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和 1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte) ...

最新文章

  1. 如何将广告始终定位到网页右下角
  2. 批量重置域用户密码(一)
  3. Keras——模型的保存、读取及加载
  4. oracle union 最多_用户来稿:我就是那个在优买计划赚钱最多的男人
  5. java中怎样避免方法被重写
  6. IOS 图片上传处理 图片压缩 图片处理
  7. p1417 烹调方案_Java 8的烹调方式–拼图项目
  8. php中cookie存的是什么,PHP中Cookie存在的作用和用法
  9. 计算机图形学E6——倒水问题emm和OpenGL没啥关系
  10. Linux centos7 安装python3.6.5 和 pip3
  11. java解决斐波那契数列(Fibonacci sequence)
  12. 【FTP】org.apache.commons.net.ftp.FTPClient实现复杂的上传下载,操作目录,处理编码...
  13. 计算机所有相关系统设置,关于win7系统5种电脑实用设置技巧
  14. 北大核心2020_“三个月不录用视为拒稿”,核心期刊投稿,编辑的这句话别有用意...
  15. javaee之用户信息增删改查案例
  16. python中的translate函数_Python:内置函数makestrans()、translate()
  17. shecodject生成免杀木马,一步过360、火绒
  18. 修复图片音频全新升级带特效喝酒神器小游戏微信小程序源码下载-多种游戏支持流量主
  19. 单独使用bable插件
  20. 这一年,熬过许多夜,也有些许收获 | 2022年终总结

热门文章

  1. C#halcon点拟合圆形函数
  2. 机械零点、MAM 文件 、 EMT标定原理
  3. C++ vector.insert的用法
  4. 拿到项目怎么开始整理PCB原理图
  5. 发布 项目_第十八期科创基金项目发布会圆满结束
  6. python接口开发django_用 Django 开发接口
  7. 让你的Tex代码更加美观就这么简单----Tex代码的自动格式化
  8. 22Java之JDBCTemplate总结
  9. JQ表单序列化变成 对象
  10. php对二维数据进行排序