关于base64编码的原理及实现

我们的图片大部分都是可以转换成base64编码的data:image。 这个在将canvas保存为img的时候尤其有用。虽然除ie外,大部分现代浏览器都已经支持原生的基于base64的encode和decode,例如btoa和atob。(将canvas画布保存成img并强制改变mimetype进行下载,会在下一篇记录)

但是处于好奇心,还是驱使我去了解下base64编码的原理。以便也在不支持原生base64编码的ie下可以得以实现。

【Base64】
-base64的编码都是按字符串长度,以每3个8bit的字符为一组,
-然后针对每组,首先获取每个字符的ASCII编码,
-然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节
-然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节
-然后将这4个8bit的字节转换成10进制,对照Base64编码表 (下表),得到对应编码后的字符。

(注:1. 要求被编码字符是8bit的,所以须在ASCII编码范围内,\u0000-\u00ff,中文就不行。
   2. 如果被编码字符长度不是3的倍数的时候,则都用0代替,对应的输出字符为=)

Base64 编码表
ValueChar ValueChar ValueChar ValueChar
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

比如举下面2个例子:
a) 字符长度为能被3整除时:比如“Tom” :

            T           o           m
ASCII: 84 111 109
8bit字节: 01010100 01101111 01101101
6bit字节: 010101 000110 111101 101101
十进制: 21 6 61 45
对应编码: V G 9 t

所以,btoa('Tom') = VG9t

b) 字符串长度不能被3整除时,比如“Lucy”:

            L           u           c           y
ASCII: 76 117 99 121
8bit字节: 01001100 01110101 01100011 01111001 00000000 00000000
6bit字节: 010011 000111 010101 100011 011110 010000 000000 000000
十进制: 19 7 21 35 30 16 (异常) (异常)
对应编码: T H V j e Q = =

由于Lucy只有4个字母,所以按3个一组的话,第二组还有两个空位,所以需要用0来补齐。这里就需要注意,因为是需要补齐而出现的0,所以转化成十进制的时候就不能按常规用base64编码表来对应,所以不是a, 可以理解成为一种特殊的“异常”,编码应该对应“=”。

有了上面的理论,那我们实现一个base64编码就容易了。
 

/**
* base64 encoding & decoding
* for fixing browsers which don't support Base64 | btoa |atob
*/

(function (win, undefined) {

var Base64 = function () {
var base64hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

// btoa method
function _btoa (s) {
if (/([^\u0000-\u00ff])/.test(s)) {
throw new Error('INVALID_CHARACTER_ERR');
}
var i = 0,
prev,
ascii,
mod,
result = [];

while (i < s.length) {
ascii = s.charCodeAt(i);
mod = i % 3;

switch(mod) {
// 第一个6位只需要让8位二进制右移两位
case 0:
result.push(base64hash.charAt(ascii >> 2));
break;
//第二个6位 = 第一个8位的后两位 + 第二个8位的前4位
case 1:
result.push(base64hash.charAt((prev & 3) << 4 | (ascii >> 4)));
break;
//第三个6位 = 第二个8位的后4位 + 第三个8位的前2位
//第4个6位 = 第三个8位的后6位
case 2:
result.push(base64hash.charAt((prev & 0x0f) << 2 | (ascii >> 6)));
result.push(base64hash.charAt(ascii & 0x3f));
break;
}

prev = ascii;
i ++;
}

// 循环结束后看mod, 为0 证明需补3个6位,第一个为最后一个8位的最后两位后面补4个0。另外两个6位对应的是异常的“=”;
// mod为1,证明还需补两个6位,一个是最后一个8位的后4位补两个0,另一个对应异常的“=”
if(mod == 0) {
result.push(base64hash.charAt((prev & 3) << 4));
result.push('==');
} else if (mod == 1) {
result.push(base64hash.charAt((prev & 0x0f) << 2));
result.push('=');
}

return result.join('');
}

// atob method
// 逆转encode的思路即可
function _atob (s) {
s = s.replace(/\s|=/g, '');
var cur,
prev,
mod,
i = 0,
result = [];

while (i < s.length) {
cur = base64hash.indexOf(s.charAt(i));
mod = i % 4;

switch (mod) {
case 0:
//TODO
break;
case 1:
result.push(String.fromCharCode(prev << 2 | cur >> 4));
break;
case 2:
result.push(String.fromCharCode((prev & 0x0f) << 4 | cur >> 2));
break;
case 3:
result.push(String.fromCharCode((prev & 3) << 6 | cur));
break;

}

prev = cur;
i ++;
}

return result.join('');
}

return {
btoa: _btoa,
atob: _atob,
encode: _btoa,
decode: _atob
};
}();

if (!win.Base64) { win.Base64 = Base64 }
if (!win.btoa) { win.btoa = Base64.btoa }
if (!win.atob) { win.atob = Base64.atob }

})(window)

 

Base64 example

 

转载于:https://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django web开发系列(五)模板

一 前言在上一节了解到视图函数处理后&#xff0c;会将结果渲染到创建的html页面&#xff0c;但html如何接收并显示视图函数返回的动态数据呢&#xff1f;最常用的做法就是使用模板(Template)&#xff0c;本节将简单介绍一下模板的作用和用法。 可以这样简单的理解模板的概念&a…

facebook 面试_如何为您的Facebook产品设计面试做准备

facebook 面试重点 (Top highlight)Last month, I joined Facebook to work on Instagram DMs and as a way to pay it forward, I 上个月&#xff0c;我加入了Facebook&#xff0c;从事Instagram DM的工作&#xff0c;作为一种支付方式&#xff0c;我 offered to help anyone…

8年了,开始写点东西了

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。今天分享一位大佬的文章…

荒径 弗罗斯特_弗罗斯特庞克,颠覆性城市建设者

荒径 弗罗斯特Most gamers are familiar with Will Wright’s famous SimCity series. It created the city building genre and there have been many attempts over the years to ape it. But few developers have been bold enough to completely deconstruct the formula; …

2012年1月份第2周51Aspx源码发布详情

WP7手指画图应用源码 2012-01-14 [VS2010] 游戏介绍&#xff1a;Windows Phone 7手指画图应用 – FingerPaint&#xff0c;您通过此游戏可以随心画一些感兴趣的东西&#xff0c;陶冶情操。操作简单&#xff0c;页面简洁。适合新手学习参考。 WP7 Car Bloke(交通工具开销记录)源…

Gitee 如何自动部署博客 Pages?推荐用这个GitHub Actions!

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。前段时间我把自己的博客…

Java io流学习总结(三)

转载于&#xff1a;https://www.cnblogs.com/ll409546297/p/7197911.html java.io几种读写文件的方式 一、Java把这些不同来源和目标的数据都统一抽象为数据流。 Java语言的输入输出功能是十分强大而灵活的。 在Java类库中&#xff0c;IO部分的内容是很庞大的&#xff0c;因为它…

现在流行的画原型图工具_原型资源图:8种流行原型工具的综合指南

现在流行的画原型图工具Although tools are not the most important things to learn as a UX designer, inevitably you need to use it in order to achieve your more important goals, to solve user’s problems. This article covers today’s 8 popular UX prototyping …

持续5个月,200+笔记,3千多人参与,邀请你来学源码~

注意&#xff1a;本文点击文末阅读原文可查看文中所有链接。我正在参加掘金年度人气作者投票活动&#xff0c;大家有空可以加微信群帮忙投票&#xff0c;感谢大家&#xff01;想起今天还没发文&#xff0c;就开放下微信群二维码&#xff0c;大家扫码进群读源码和帮忙投票吧。群…

自己动手开发调试器 01

背景: 在做XXX编译器检证时经常需要区分是代码端错误&#xff0c;还是编译器端错误&#xff0c;因此对代码进行调试是必不可少的。但是狗日的甲方并没有提供对应的调试器XXXDB&#xff0c;而用GDB调试XXX生成的可执行程序很不稳定&#xff0c;经常出现异常&#xff0c;干脆…

02如何抓住重点,系统高效地学习数据结构与算法?

以下内容总结自极客时间王争大佬的《数据结构与算法之美》课程&#xff0c;本文章仅供个人学习总结。 什么是数据结构?什么是算法? 从广义上讲&#xff0c;数据结构就是指一组数据的存储结构。算法就是操作数据的一组方法。 类比图书馆的书籍&#xff0c;我们如果想找一本书可…

第2年,倒数第3天,1.5万票,感动!

1源码共读大家好&#xff0c;我是若川。众所周知。从8月份开始&#xff0c;我组织了源码共读活动&#xff0c;至今已经有5个月了&#xff0c;每周一期&#xff0c;进行到了第18期。每周坚持写源码解读文章&#xff0c;每天坚持答疑解惑&#xff0c;帮助了很多人学会看源码&…

启发式搜索给神经网络_神经科学如何支持UX启发式

启发式搜索给神经网络重点 (Top highlight)Interaction and UX designers have long known and used heuristics to guide the creation of a user-friendly interface. We know empirically that these principles work, and they make “common sense”. These heuristics th…

Django实战(1):需求分析和设计

Depot是《Agile Web Development with Rails》中的一个购物车应用。 该书中用多次迭代的方法&#xff0c;逐步实现购物车应用&#xff0c;使很多人走上了rails开发的道路。 遗憾的是Django世界中好像没有类似的指引&#xff0c;也许是因为pythoner 不需要具体的例子。 但是如果…

使用 apiDoc 为你的Node.js API 生成文档

翻译&#xff1a; 疯狂的技术宅 原文&#xff1a;jonathas.com/documenting… 未经许可&#xff0c;禁止转载&#xff01; 当你为其他开发人员&#xff08;前端&#xff0c;桌面&#xff0c;移动等&#xff09;开发 API 时&#xff0c;需要生成一份风格良好的文档&#xff0c;以…

海浪 shader_海浪下的发现

海浪 shaderI’ve been playing Subnautica for over 25 hours now, and likely have at least that many more to go. The game puts you in the shoes of a crew member on the Aurora, a spaceship that suffers a catastrophic incident and plummets to the largely ocean…

最后一天,特邀小姐姐配音拉票,今日可投28票

1源码共读大家好&#xff0c;我是若川。最后一天&#xff0c;特邀小姐姐配音拉票&#xff0c;超级好听。众所周知。从8月份开始&#xff0c;我组织了源码共读活动&#xff0c;至今已经有5个月了&#xff0c;每周一期&#xff0c;进行到了第18期。每周坚持写源码解读文章&#x…

NET中使用Memcached的相关资源整理

本文转自&#xff1a;http://www.cnblogs.com/dudu/archive/2009/07/19/1526407.html Memcached官方站点&#xff1a;http://www.danga.com/memcached / Memcached Win32 1.2.6下载&#xff1a;http://code.jellycan.com/memcached/ 安装帮助&#xff1a;Windows下的.NET Memca…

FFMPEG 视频图像解封装解码

FFMPEG4.0 音频解码解封装FFMPEG 音频封装编码 下面的函数方法基于最新的FFMPEG 4.0&#xff08;4.X&#xff09;&#xff1a;本文讲是如何从一个视频文件中提取出其中的图像数据&#xff0c;并将图像数据保存到文件中。 解码解封装的过程与音频差不多&#xff0c;具体如下&…

对数据可视化的理解_使数据可视化更容易理解

对数据可视化的理解Data is weaving its way into almost all aspects of our lives since the past decade. Our ability to store more information in smaller and smaller spaces has encouraged us to make sure we leave no information out. The ease of collecting inf…