「来源: |React ID:react_native」
作者: 黄鹂
详解 base64 原理
案例:'鹅' --> 经过base64编码 --> 6bmF
那它怎么编码的呢
以 '鹅' 字为例
base64 对应的编码表:
**字符串转base64的转码规则:第一步,将每三个字节作为一组,一共是24个二进制位。第二步,将这24个二进制位分为四组,每个组有6个二进制位。第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。第四步,根据上表,得到扩展后的每个字节的对应符号,这就是base64的编码值。
异常情况处理
二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的base64编码,再在末尾补上一个"="号。一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的base64编码,再在末尾补上两个"="号。使用 node 的 buffer 进行处理:
demo1.js
const CHARTS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';functionencode {let buf = Buffer.from;let result = '';let suffix = '';for { result += b.toString.padStart }if === 4) { // 一个字节的情况 suffix = '='; result += '00'; }if === 2) { // 剩余两个字节的情况 suffix = '=='; result += '0000'; }return result.match/g).map).map.join + suffix }functiondecode {var result = '';for {if break; result += ).toString.padStart } var list = result.match/g).map=>{returnparseInt })return Buffer.from.toString }var ss = encode;console.log // 5pyx5piGbQ==console.log) // 朱昆m上述代码阐述的编解码的过程。但是如果去看第三方库的代码,会发现还是看不懂的~
为什么会看不懂了?
原因:
为了兼容浏览器的Unicode编码,需要先对Unicode进行编解码。引入二进制操作,提高位操作效率;举例:
image.png鹅 -> Unicode字符集 -> 0b1001 1110 0100 0101鹅 -> utf8编码 -> 0b1110 1001 1011 1001 1000 0101
Unicode转utf8:
将高位字节的高四位,与1110 形成一个新字节。将高位字节的低四位,与低位字节的高两位,与10形成一个新字节将地位字节的低六位与10 形成一个新字节。三个新字节按顺序排布,形成一个新的编码,就是utf编码。utf8转Unicode:将上述的顺序翻转。就可以返回新的Unicode编码。
let _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";console.log))functionencode {var output = "";var chr1, chr2, chr3, enc1, enc2, enc3, enc4;var i = 0;// 将Unicode,变成 utf8 input = _utf8_encode; // 将utf8 转成 base64while { chr1 = input.charCodeAt; chr2 = input.charCodeAt; chr3 = input.charCodeAt; enc1 = chr1 >> 2; enc2 = << 4) | ; enc3 = << 2) | ; enc4 = chr3 & 63;if ) { enc3 = enc4 = 64; } elseif ) { enc4 = 64; } output = output + _keyStr.charAt + _keyStr.charAt + _keyStr.charAt + _keyStr.charAt; }return output;}functiondecode {var output = "";var chr1, chr2, chr3;var enc1, enc2, enc3, enc4;var i = 0; input = input.replace;//将base64转化成utf8while { enc1 = _keyStr.indexOf); enc2 = _keyStr.indexOf); enc3 = _keyStr.indexOf); enc4 = _keyStr.indexOf); chr1 = | ; chr2 = << 4) | ; chr3 = << 6) | enc4; output = output + String.fromCharCode;if { output = output + String.fromCharCode; }if { output = output + String.fromCharCode; } }// 将utf8转成浏览器认识的Unicode output = _utf8_decode;return output;}function_utf8_encode { // 将Unicode,变成 utf8 string = string.replace;var utftext = "";for {var c = string.charCodeAt;if { utftext += String.fromCharCode; } elseif && ) { utftext += String.fromCharCode | 192); utftext += String.fromCharCode | 128); } else { utftext += String.fromCharCode | 0b11100000); utftext += String.fromCharCode & 0b111111) | 0b10000000); utftext += String.fromCharCode | 0b10000000); } }return utftext;}function_utf8_decode { // 将utf8转成Unicodevar string = "";var i = 0;var c = c1 = c2 = 0;while { c = utftext.charCodeAt; // 第一个字节if { string += String.fromCharCode; i++; } elseif && ) { c2 = utftext.charCodeAt; string += String.fromCharCode << 6) | ); i += 2; } else { c2 = utftext.charCodeAt; // 第一个字节 c3 = utftext.charCodeAt; // 第二个字节 string += String.fromCharCode << 12) | << 6) | ); i += 3; } }return string;}重点:上述代码中,明白二进制的移位操作,和Unicode码的转码规则。理解起来难度就不大了。
解释:
Unicode字符集 相当于 字和词的汇总,相当于语言的概念;utf8编码 是一种编码格式, 相当于汉语,英语的概念。鹅 在汉语中叫 '鹅',在 英语中叫 'goose' 汉语,英语放在计算机里面就相当于一种编码,类似utf8,gbk。参考文档:
base64原理程序员必备:
彻底弄懂常见的7种中文字符编码
Unicode 和 UTF-8 有什么区别base64笔记