js逻辑封装_将文本转化为baseb4格式(base64加密解密)

知识点1—进制转换

10进制转换为其他进制

在Number原型链上存在方法toString方法,用于将10进制转换为其他进制(2-36)
语法

// 指定要用于数字到字符串的转换的基数 (从 2 到 36)。如果未指定 radix 参数,则默认值为 10
num.toString([radix])

tips: 在使用数字调用方法时,建议加(),不然数字后面的点会被认为是小数点而不是方法调用。

返回值:对应进制的字符串

(33).toString() // '33'
(20005).toString(2) // '100111000100101'
(0x16).toString(16) // '16'

注: 若是没有标注,num默认为10进制
         以0x开始的数据表示16进制

负数

Number原型链上的toString方法将10进制转化成其他进制尽是在num为正数时起作用

(-1000).toString(2) // '-1111101000' 但是实际的值为 0000011000 

负数的十进制转化为2进制
负数在内存中是以补码的形式存储的,因此若是计算负数的二进制,需要先计算正值的二进制然后计算期补码;

计算补码: 先对二进制值逐位取反再对取反后的二进制数加1得到补码;

举例说明:-100转化为二进制

  • [1] 100转化为二进制为 1100100
  • [2] 逐位取反 0011011
  • [3] 加1 0011111
  • -100的二进制为 0011111
其他进制转化为10进制

其他进制转换为10进制的规则为:按权展开相加

16进制转化为10进制

  • 在16进制中ABCDEF表示的分别是10,11,12,13,14,15;
  • 从右向左按权展开相加
  • eg:52E4转换为10进制过程为

    52E4 = 5 * 10^0 + 2 * 10^1 + 14 * 10^2 + 4 * 10^3
              = 5+32+3584+16384
              = 20005

2进制转化为10进制

  • 从右向左按权展开相加
  • eg:

知识点2—ASCII码与Unicode

ASCII码
  • 在计算机内部,所有信息都是以二进制(0,1)进行存储的。

  • 每一个二进制(bit)有0和1两种状态

    • 一个字节有8个二进制位,八个二进制位就可以组合出256种状态。
    • 也就是说,一个字节一共可以用来表示256种不同的状态。
  • 美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。

    • ASCII 码一共规定了127个字符的编码,比如空格space是32(二进制00100000),大写的字母A是65(二进制01000001)。
    • 这127个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的一位统一规定为0
    • 以下这些编号呢就被称为码点,码点可以称为这些字符的身份证号码在这里插入图片描述
非ASCII
  • 英语用127个符号编码就够了,但是用来表示其他语言,127个符号是不够的。比如,在法语中,字母上方有注音符号,它就无法用 ASCII 码表示。

  • 于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。

  • 这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。

  • 但是,这里又出现了新的问题 -> 不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。

  • 但是不管怎样,所有这些编码方式中,0--127表示的符号是一样的不一样的只是128--255的这一段

  • 至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是 GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示 256 x 256 = 65536 个符号。

Unicode

正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。

可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码被称为万国码。

tips:知道为什么 txt文件使用vscode打开会乱码吗?
       原因:vscode默认使用的编码方式为utf-8而txt文件的编码方式为 GB2312编码格式,因此会乱吗;
       解决:若是想txt文件在vscode打开,在当前页面修改编码方式

unicode获取码点与对应的字符
fromCharCode

formCharCode是String的静态方法,用于将 Unicode 编码转为一个字符!

语法:String.fromCharCode(num1[, ...[, numN]])

  • num1, …, numN : 一个或多个 Unicode 值,即要创建的字符串中的字符的 Unicode 编码 (范围介于0~65535,因为0~65535是unicode的码点,超出就没有意义了)

返回值:返回一个长度为 N 的代表 Unicode 编码的字符;

举例说明:

String.fromCharCode(65) // 'A'
String.fromCharCode(25105) // '我'
charCodeAt

语法:string.charCodeAt(index)

返回值:指定 index 处字符 对应的Unicode码点(取值范围为0-65535)

UTF-32(不推荐)

UTF-32统一使用4个字节表示一个字符,虽然这样可以使得全世界使用统一的编码方式,但是占用存储空间,通信效率变低。

比如说ASCII码, 每个ASCII码表示的字符都需要在前面3个字符补足0才行;及时时中文BGK表示的字符前面都需要使用2个字符补足0才行,这降低了通信效率,因此不被采纳。

UTF-8(普遍使用)

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一。

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8 的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的

2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

下表总结了编码规则,字母x表示可用编码的位。
在这里插入图片描述
跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

下面,还是以汉字我为例,演示如何实现 UTF-8 编码。

我的Unicode为25105,转换为十六进制为6211(处于第三行),转换为二进制为 110001000010001;因此我使用UTF-8编码应该是

从右向左按照6位一组进行划分 110 001000 010001
划分完毕之后添加到 1110xxxx 10xxxxxx 10xxxxxx中去,若是空却使用0补齐
结果为 11100110 10001000 10010001
转换为16进制为 E68891

知识点3—URL编码/解码

[1] 为什么要进行URL编码

先看如下案例

  • 发送请求去获取数据,请求的url如下

    https://www.baidu.com?wd=hello word&name=超超&age=18&sex=女

    但是在浏览器打开,实际请求的url变为如下

    https://www.baidu.com?wd=hello%20word&name=%E8%B6%85%E8%B6%85&age=18&sex=%E5%A5%B3

  • 为什么url会自己发生改变呢?

    • 这是由于在网络请求中,只能采用A-Z a-z 0-9 以及字符 - _ . ! ~ * ' ( )这些字符,若是遇到汉子或一些特殊字符,就会先进行URL编码再发送请求。
  • 看到这里或许会觉得这也无所谓,只要在接收到url之后再进行解码即可!但是问题在于标准国际组织并没有规定具体的编码方法,而是将决定权交给了浏览器,也就是说不同的浏览器的编码方式可能会不同,那在解码时就需要进行判断比较麻烦 —> 若是使用js在发送请求之前对URL进行编码就实现了编码方式的统一!

[2] encodeURIComponent方法
  • 作用:encodeURIComponent函数可把字符串作为 URI 组件进行编码

  • 语法:encodeURIComponent(str);

  • 编译过程:该方法不会对 ASCII 字母和数字进行编码,也不会对这些 安全的ASCII 标点符号(- _ . ! ~ * ’ ( ))进行编码,只会对特殊字符进行编码。

    • 安全ASCII字符:保留;
    • 非安全ASCII字符:使用utf-8对其进行编码得到对应的字节,然后对每个字节进行百分号编码(将16进制的0x替换为%)
      • 举例说明:‘中文’转化为utf-8为 0xE4 0xB8 0xAD 0xE6 0x96 0x87, 进行百分号编码最终结果为 %E4 %B8 %AD %E6 %96 %87
        encodeURIComponent('中文') // '%E4%B8%AD%E6%96%87'
        
  • 举例说明
    // 不会对数字与英文字符进行编码
    encodeURIComponent("156xxxxxxxx") // '156xxxxxxxx'
    
    // 会对特殊字符进行编码
     encodeURIComponent("hello word") // 'hello%20word'
    
    // 会对非AscII码进行编码
     encodeURIComponent("中国真棒") // '%E4%B8%AD%E5%9B%BD%E7%9C%9F%E6%A3%92'
    
  • 使用场景:
    • 在使用url进行参数传递的时候,当参数出现空格这样的特殊字段,后台只可以读取到空格前的内容,后面内容丢失,造成数据读取失败; 但是如果用encodeURIComponent函数将这些特殊字符进行转义,后台就可以成功读取传递的数据了;
    • 用于base编码过程;
[3] decodeURIComponent

decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码

举例说明:

//'%E4%B8%AD%E5%9B%BD%E7%9C%9F%E6%A3%92'
encodeURIComponent('中国真棒') 
// '中国真棒'
decodeURIComponent('%E4%B8%AD%E5%9B%BD%E7%9C%9F%E6%A3%92')

知识点4—base64编码/解码

base64定义

所谓Base64,就是选出64个字符

  • 小写字母a-z、
  • 大写字母A-Z、
  • 数字0-9、
  • 符号"+“、”/"
  • 再加上作为垫字的"="

实际上是65个字符作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。
使得二进制数据在解释成 radix-64 的表现形式后能够用 ASCII 字符串的格式表示出来。

base64转换规则

base64转换规则具体来说可以分为四步:

第一步,将每三个字节作为一组,一共是24个二进制位。
第二步,将这24个二进制位分为四组,每个组有6个二进制位。
第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
第四步,根据下表,得到扩展后的每个字节的对应符号,这就是Base64的编码值。

  0 A  17 R   34 i   51 z

  1 B  18 S   35 j   52 0

  2 C  19 T   36 k   53 1

  3 D  20 U   37 l   54 2

  4 E  21 V   38 m   55 3

  5 F  22 W   39 n   56 4

  6 G  23 X   40 o   57 5

  7 H  24 Y   41 p   58 6

  8 I   25 Z   42 q   59 7

  9 J  26 a   43 r   60 8

  10 K  27 b   44 s   61 9

  11 L  28 c   45 t   62 +

  12 M  29 d   46 u   63 /

  13 N  30 e   47 v

  14 O  31 f   48 w   

  15 P  32 g   49 x

  16 Q  33 h   50 y

因为,Base64将三个字节转化成四个字节,因此Base64编码后的文本,会比原文本大出三分之一左右。

举例说明

举一个具体的实例,演示英语单词Man如何转成Base64编码。
在这里插入图片描述

  • 第一步,“M”、“a”、"n"的ASCII值分别是77、97、110,对应的二进制值是01001101、01100001、01101110,将它们连成一个24位的二进制字符串010011010110000101101110。

  • 第二步,将这个24位的二进制字符串分成4组,每组6个二进制位:010011、010110、000101、101110。

  • 第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节:00010011、00010110、00000101、00101110。它们的十进制值分别是19、22、5、46。

  • 第四步,根据上表,得到每个值对应Base64编码,即T、W、F、u。

因此,Man的Base64编码就是TWFu。

字节数不足三的情况

如果字节数不足三,则这样处理:

  • a)二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。

    • 比如,“Ma"这个字符串是两个字节,可以转化成三组00010011、00010110、00010000以后,对应Base64值分别为T、W、E,再补上一个”="号,因此"Ma"的Base64编码就是TWE=。
  • b)一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。

    • 比如,“M"这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个”="号,因此"M"的Base64编码就是TQ==。
base64编码对应的方法
btoa

btoa是binary to ascii的缩写;

作用:btoa是window对象的方法,作用是将二进制数据ASCII字符串转换成一个base64编码过的ASCII字符串

语法:btao(stringToEncode)

  • stringToEncode 是一个需要编码的二进制字符串;
  • 传入的字符串将视为一个二进制字符串 -> 将字符串中的每一个字节都视为一个二进制数据字节;
  • 因此:每个字符只能使用一个字节表示,若是其中包含了需要使用超过一个字节才能表示的字符,你就会得到一个错误,因为这个字符串不能被看作是二进制数据;
  • 因此btoa能够编码(全部的)ASCII字符却不能编码(超过一个字节的)Unicode字符。

举例说明:

  • ASCII字符串能够正常编码;
    var str = "hello world";
    var demo = btoa(str);
    console.log(demo);// aGVsbG8gd29ybGQ=
    
  • Uniconde字符串中存在超过1个字节的字符则不能正常编码,会报如下错误:

    var str = "中国真棒";
    var demo = btoa(str);
    console.log(demo);
    

    在这里插入图片描述

  • 若是想要将Unicode字符编码为base64,在编码之前还需要使用encodeURIComponent方法将Unicode字符进行转换,再进行base64编码;

atob

atob:是ascii to binary的缩写
作用: atob是window的方法,作用是对经过 base-64 编码的字符串进行解码

var demo = "aGVsbG8gd29ybGQ=";
var str = atob(demo);
console.log(str);//hello world

若是在加密过程中使用了encodeURIComponent方法进行编码就要在解码过程中使用decodeURIComponent进行解码

重点-base64编码解码方法封装

js-base64编码
encode (str) {
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
    function toSolidBytes (match, p1) {
      return String.fromCharCode('0x' + p1)
  }))
}
js-base64解码
decode (str) {
  return decodeURIComponent(atob(str).split('').map(function (c) {
     return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
  }).join(''))
}
插件-js-base64

该插件的原理就是上述base64编码解码过程

安装:npm install --save js-base64

引入:

import { encode, decode } from 'js-base64';

使用

// 加密
encode(encodeURIComponent('张三')) // '5byg5LiJ'
// 解密
decode(decodeURIComponent('5byg5LiJ')) // 张三
六个方法的综合应用(插件的原理)
encode (str) {
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
    function toSolidBytes (match, p1) {
      return String.fromCharCode('0x' + p1)
  }))
}

[1] 对“中国真棒”进行base64进行编码

btoa(“中国真棒”) 
  • 报错-> 不能对超过1个字节的字符进行编码

[2]将“中国真棒”拆解为多个单字节的字符串

  • [2.1]将字符编译为单个字节的字符
    encodeURIComponent('中国真棒')  //  '%E4%B8%AD%E5%9B%BD%E7%9C%9F%E6%A3%92'
    
  • [2.2]将编译后的字符转换为Unicode
    '%E4%B8%AD%E5%9B%BD%E7%9C%9F%E6%A3%92'.replace(
      /%([0-9A-F]{2})/g,
      function toSolidBytes(match,p1){
        return String.fromCharCode('0x' + p1) // 将UTF-16的数转化为对应的Unicode 编码的字符
      }
    ) // '中å\x9B½ç\x9C\x9Fæ£\x92'
    

[3] 将单子节自符进行base 64编码

btoa('中å\x9B½ç\x9C\x9Fæ£\x92') //'5Lit5Zu955yf5qOS'

[4] 对btoa方法编码后的字符进行解码

atob('5Lit5Zu955yf5qOS') // '中å\x9B½ç\x9C\x9Fæ£\x92'

[5] 将单字节字符还原-》还原为十六进制的转义序列

'中å\x9B½ç\x9C\x9Fæ£\x92'.split('').map(item => '%'+('00'+item.charCodeAt(0).toString(16)).slice(-2)).join('') 
// '%e4%b8%ad%e5%9b%bd%e7%9c%9f%e6%a3%92'

[6] 由于改字符使用过 encodeURIComponent编码过,因此使用decodeURIComponent进行解码

decodeURIComponent('%e4%b8%ad%e5%9b%bd%e7%9c%9f%e6%a3%92') // '中国真棒'

参考文档

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值