Base64 解读


背景:

在项目中,我们会上传文件或者图片到服务器,需要的时候再下载,这个时候我们可能会听到,把对方传来的 Base64 解码在上传到服务器;或者,直接把 Base64 码保存到数据库。所以就了解了一下这个 Base64

Base64 编码转换方式

本段引自阮一峰的网络日志

下面结合文字和具体例子,保证可以看得懂。

所谓 Base64,就是说选出 64 个字符:小写字母 a-z、大写字母 A-Z、数字 0-9、符号“+”、“/”(再加上作为垫字的“=”,实际上是65个字符)作为一个基本字符集。然后其他所有符号都转换成这个字符集中的字符。

具体来说转换方式可以分为以下四步:

  • 将每三个字节作为一组,一共是 24 个二进制位
  • 将这 24 个二进制分为 4 组,每组有 6 个二进制位
  • 在每组前面加上两个 0 ,扩展成 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

转码后的文本,会比未转码的大1/3左右,因为是将三个字节扩充到4个字节

具体例子:

演示英语单词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 。

为什么用?

  • 二进制文件转换为字符串,方便传输
  • 简单加密

那么,假如是我们自己做的小项目,就是自己上传文件到服务器,那么就不需要 Base64,直接上传即可。此时Base64 意义不大。

在企业级项目中,前后端分离,很可能有很多个中心,而你的服务只是其中一个中心的一个微小服务,当别人需要使用你的服务的时候,难道别人直接把数据流传送给你?传一个字符串就能解决的事情,为什么要搞得那么复杂。

public class ForCheckAnyObject {

    public static void main(String args[]) throws IOException {

        String filePath = "D:" + File.separator + "2.txt";

        File file = new File(filePath);
        InputStream is = new FileInputStream(file);
        //is.available():返回读取文件大小这多的字节
        byte[] bytes = new byte[is.available()];
        is.read(bytes);
        is.close();

        // sun.misc.BASE64Encoder
        BASE64Encoder encoder = new BASE64Encoder();
        String encodeString = encoder.encode(bytes);
        System.out.println(encodeString);

        // JDK8 新加入的 java.util.Base64
        String encodeString1 = Base64.getEncoder().encodeToString(bytes);
        System.out.println(encodeString1);
    }
}

//经测试两个类生成的 Base64 码一样
//yKjP3rT6wusNCg==

分析上面的代码

  • is.available():返回读取文件大小这么多的字节(再也不用想应该怎么样设置这个数组的大小了)
  • sun.misc.BASE64Encoder 类对二进制数据进行加密
  • java.util.Base64 类对二进制数据进行加密

具体分析

下面来分析两个不同类的具体用法

sun.misc.BASE64Encoder

这 sun 公司的一个类,虽然在我们开发中不需要引入第三方的库,但是 JDK8 中已经有替代方案,当然在 JDK8 以前就使用这个吧。

        BASE64Encoder encoder = new BASE64Encoder();
        String encodeString = encoder.encode(bytes);

        BASE64Decoder decoder=new BASE64Decoder();
        byte[] bytes1=decoder.decodeBuffer(encodeString);
        

上面就是正常 new 初始化,再进行加/解密

java.util.Base64

这是 JDK8 开始才引入的类

//加密
String encodeString1 = Base64.getEncoder().encode(bytes).toString();
//解密
bytes2=Base64.getDecoder().decode(encodeString1);

下面是 JDK8 中 java.util.Base64 类的源码

//因为是私有构造函数,所以不能使用 new 实例化
private Base64() {}

//提供静态方法,实例化 Encoder 对象
 public static Encoder getEncoder() {
         return Encoder.RFC4648;
    }


// java.util.Base64 类中的静态内部类
public static class Encoder {
	///
     public byte[] encode(byte[] src) {
         
     }
    
    public byte[] decode(String src) {
        ///
    }
   ///
}
//也是返回一个 Encoder 对象,只不过加密的 64 个字符;
// 将符号“+”、“/” 换成了 '-', '_',其余操作不便
Base64.getUrlEncoder().encode(bytes);

// 主要是URL中反斜杠 /有特殊的含义,直接编码会不太安全,所以URL编码会使用下划线 _ 来替代 /。

总结

核心作用应该是传输数据的正确性,有些网关或系统只能使用 ASCII 字符。Base64 就是用来将非 ASCII 字符的数据转换成 ASCII 字符的一种方法,而且 base64 特别适合在 http,mime 协议下快速传输数据。

加密的作用很小,我们可以直接用 JDK 提供的方法就解密了,所以最主要的还是数据传输的正确性,和方便

这个是作用在二进制数据上面的。即先把一个文件转为二进制,在对其进行加密,最终我们得到的字符串其实就是文件的内容

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值