最近因为工作需要对一些文件上传需要进行base64编码操作,于是就自己温习了一下base64编码集的原理,感觉收获良多,在这里和大家分享一下!
因为我们都是在互联网上数据的传输最终都会以二进制的方式传输,文件上传的I/O流也不例外,最终都是二进制数组的方式传输,但是二进制保存到数据库中却是不太现实的,因为它是在太长了。
例子:
我们将一个本地文件同I/O读取出来,并且转换成byte组,在装换成base64编码集的结果。
代码如下:
public static void main(String[] args) throws IOException {
String path = "C:\\logs\\IntelAPO.log";
FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len = -1;
while ((len = fis.read(buf)) != -1) {
baos.write(buf,0,len);
}
byte[] baostype = baos.toByteArray();
baos.close();
fis.close();
//byte数组的值[70, 65, 84, 65]
//转换成二进制是:01000110010000010101010001000001
//我们将这个二进制断开一下 01000110 01000001 01010100 01000001
System.out.println(Arrays.toString(baostype));
byte[] base64 = Base64.getEncoder().encode(baostype);
//转成成base64的结果:WyAgRkFUQUxdW1c=
System.out.println(Base64.getEncoder().encodeToString(baostype));
}
我们可以看到本地文件的二进制数组是如下:
[70, 65, 84, 65]
如果们给他转成二进制格式是如下:
01000110 01000001 01010100 01000001
因为数字的长度4位,所有它是有4位字节组成,1个字节由8位二进制组成,我们可以通过得到如上的二进制。
下面我们详细讲述一下base64如何把这个二进制转成base64的编码集。
base64编码集的底层是把原有的3个二进制字节的24位二进制分成4份,变成4个6位的二进制,在对着4个6位二进制的前面加上2个0进行补位,这样就变成4个字节32个二进制。而生成的新的一个字节的前面两位为0,所有这样的字节换算成十进制的大小范围只能在0到63之间。如果字节数不是3的整数倍的时候,我们就需要在原来的字节后面添加一个或者两个零指的字节,使其字节长度是3的整数倍,同样需要在base64编码集编码后的字符串的后面添加一个或者两个“=”,表示添加的零值字节数。
这里简单科普一下:一个字节又被称作一个ASCII码,也就是有8位二进制组成,换算成十进制的取值范围就是-128到127之间。
而我们采用的byte字节类型,byte字节类型的取值类型是0到255,所以当前两位都为0的时候,取值范围就是0到63之间。
那么我们按照上面的规则对如下的一个4位字节的二进制进行转成:
0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
第一件事我们要在原来的4个字节的后面添加两个零值字节变成如下结果:
0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
第二件事我们给这个6个字节的进行6位一组重新划分,划分结果如下:
0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
第三件事对重新划分的6位在前面进行补位操作补上0得到的格式如下:
0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
17
36
5
20
16
16
0
0
这样我们就得到一个8个字节的8位二进制,左边是8位二进制,而右边是十进制的值。
第四件事我们就是需要对照base64的码表:
0 | A | 8 | I | 16 | Q | 24 | Y | 32 | g | 40 | o | 48 | w | 56 | 4 |
1 | B | 9 | J | 17 | R | 25 | Z | 33 | h | 41 | p | 49 | x | 57 | 5 |
2 | C | 10 | K | 18 | S | 26 | a | 34 | i | 42 | q | 50 | y | 58 | 6 |
3 | D | 11 | L | 19 | T | 27 | b | 35 | j | 43 | r | 51 | z | 59 | 7 |
4 | E | 12 | M | 20 | U | 28 | c | 36 | k | 44 | s | 52 | 0 | 60 | 8 |
5 | F | 13 | N | 21 | V | 29 | d | 37 | l | 45 | t | 53 | 1 | 61 | 9 |
6 | G | 14 | O | 22 | W | 30 | e | 38 | m | 46 | u | 54 | 2 | 62 | + |
7 | H | 15 | P | 23 | X | 31 | f | 39 | n | 47 | v | 55 | 3 | 63 | / |
对照上面的base64码表我们很重找到结果是如下的:
RkFUQQ==
综上所述我们可以很清晰了解到base64的编码格式。