base64编码算法

Base64

编码

选出64个字符作为一个基本字符集 A-Z. a-z. 0-9. + / =

  1. 将每三个字节作为一组,一个是24个二进制位
  2. 将这24个二进制位分成4组,每组6个二进制位
  3. 前面每组前面补00 变成8位二进制,最后就扩展成32个二进制位,也就是4个字节
  4. 根据每个字节,转换成的10进制,对应转码表,进行转换

举例 dog

  1. 三个字节一组 每个字节转换成ascii码
  2. d => 100 => 二进制=> 01100100
  3. o => 111 => 二进制 => 01101111
  4. g => 103 => 二进制 => 01100111
  5. 分4组
  6. 011001。 000110。 111101 100111
  7. 补0
  8. 00011001。 00000110。 00111101 00100111
  9. 转10进制25。6。61。39。
  10. ZG9n

注意事项

  1. 如果字节数不够3位

  2. 如果只有2位字节 将这两个字节的一共16个二进制位 转换成3组 6 6 4 最后一位数由于只有4位,所以前后各需要补00,这样得到一个三位的base64编码,再在末尾补上一个=号

    1. Ma
    2. M => 77 => 01001101
    3. a => 97 => 01100001
    4. 00010011,00010110,00000100
    5. 19 22. 4 => TWE=
  3. 一个字节的情况,将这个字节的8个二进制位 转换成(6,2)最后一组除了前面加00 后面需要加0000,这样得到的一个base64编码在末尾加上两个=号

    1. M
    2. M => 77 => 01001101
    3. 00010011,00010000
    4. 19, 16 => TQ==
  4. Man

    1. M转ascii 77
    2. a转ascii 97
    3. n转ascii110
    4. 01001101 01100001 01101110
    5. 6位分组 010011 010110 000101 101110
    6. 补0. 00010011 00010110 00000101 00101110
    7. 19 22 5 46
    8. base64映射编码 T W F u

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789+/

数值 字符 数值 字符 数值 字符 数值 字符
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

解码

从上面的编码算法,每三个字符为一组编码产生4个字符,那么结果便是逆向算法

  1. 将每4个字符为一组,找到每个字符对应的base64转码值
  2. 将4个ascii值变成二进制的形式,此时应该是8位的二进制,此时去掉前面的00,每组得到6位,一共24个二进制
  3. 将剩下的24个二进制分成3份,就说三个字节
  4. 转换每个字节对应的ascii值
这里写图片描述

举例 T W F u

  1. base64映射表查找 19 22 5 46
  2. 二进制010011。010110。000101。 101110
  3. 四变3 6=>8
  4. 01001101 01100001 01101110
  5. 77 97 110
  6. M a n

算法

1.

var codeMapStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789+/'

/**
 * base64编码
 * @param {*} str string
 */
function encode(str = '') {
    var reg = /([\w\W]{3})(?=[\w\W])/g
    // 通过逗号分组,每3个一组
    str = str.replace(reg, function (_, $1) {
        return `${$1},`
    })
    var arr = str.split(',')
    // 1。每三位分组
    return arr.map(function(item) {
        return _encode(item)
    }).join('')
}

// 每三位字符编码一次
function _encode(str) {
    if (!str) {
        return ''
    }
    var binaryStr = ''
    for (var i = 0; i < str.length; i++) {
        if (str[i]) {
            binaryStr += charToBinary(str[i])
        }
    }
    // 这里不能直接new Array(4)如果这样,默认情况下去遍历数组,没有初始化过的数据不会进入遍历
    var arr = [undefined, undefined, undefined, undefined]
    // 判断str长度
    if (str.length === 3) {
        arr[0] = '00' + binaryStr.slice(0, 6)
        arr[1] = '00' + binaryStr.slice(6, 12)
        arr[2] = '00' + binaryStr.slice(12, 18)
        arr[3] = '00' + binaryStr.slice(18, 24)
    } else if (str.length === 2) {
        arr[0] = '00' + binaryStr.slice(0, 6)
        arr[1] = '00' + binaryStr.slice(6, 12)
        arr[2] = '00' + binaryStr.slice(12) + '00'
    } else if (str.length === 1) {
        arr[0] = '00' + binaryStr.slice(0, 6)
        arr[1] = '00' + binaryStr.slice(6) + '0000'
    }
    return arr.map(function(item) {
        if (!item) {
            return '='
        }
        return codeMapStr[binaryToInt(item)]
    }).join('')
}
function charToBinary(char) {
    var code = char.charCodeAt()
    var binary = code.toString(2)
    // 补到8位数
    binary = binary.length === 6 ? '00' + binary : binary.length === 7 ? '0' + binary : binary
    return binary
}

// 二进制转十进制
function binaryToInt(binary) {
    return parseInt(binary, 2)
}

/**
 * base64解码
 * @param {*} str 
 */
function decode(str) {
    // 通过分组,每4个一组
    var reg = /([\w\W]{4})(?=[\w\W])/g
    // 通过逗号分组,每4个一组
    str = str.replace(reg, function (_, $1) {
        return `${$1},`
    })
    var arr = str.split(',')
    // 1。每三位分组
    return arr.map(function(item) {
        return _decode(item)
    }).join('')
}

// 每四个一组执行
function _decode(str) {
    if(!str) {
        return ''
    }
    
    // 转化成二进制
    var binaryStr = ''
    for (var i = 0; i < str.length; i++) {
        if (str[i] !== '=') {
            var code = codeMapStr.indexOf(str[i])
            binaryStr += padLeft(code.toString(2), 6, '0')
        }
    }
    var res = [binaryStr.slice(0, 8), binaryStr.slice(8, 16), binaryStr.slice(16, 24)]
    return res.filter(function(item) {
        return item !== undefined
    }).map(function(item) {
        return String.fromCharCode(binaryToInt(item))
    })
}

// 前面补位
function padLeft (str, len, padChar) {
    return new Array(len - str.length + 1).join(padChar || '') + str
}

module.exports = {
    encode: encode,
    decode: decode
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。