摘要
本文将讲述HEX
和Base64
,编码的规则。
HEX编码
hex编码也称之为Base16 编码
就是把一个字节
,用十六进制来表示, 表示的结果得是字符形式的。 说过程大家就会更加容易理解
比如说字符的 ‘a’,在计算机底层存储的是 0110 0001
,对应的16进制就是61
,它对应的字符 是'61'
也就是说 ‘a’ 经过HEX编码转化成了 '61'
,从计算存储二进制的角度是 从0110 0001
经过HEX编码成了 0011011000110001
,占用的存储扩大了一倍。
其他任意二进制数据(字节为单位)都可以转化。
代码演示:
byte[] src = "a".getBytes(StandardCharsets.UTF_8);
byte[] encoded = Hex.encode(src);
System.out.printf("字符串'%s'编码后的字符结果:'%s'%n",new String(src,StandardCharsets.UTF_8),new String(encoded,StandardCharsets.UTF_8));
System.out.printf("原长度:%d,编码后的长度:%d, 编码后是原来的%.2f%n",src.length,encoded.length,(double)(encoded.length)/src.length);
输出结果为61
字符串'a'编码后的字符结果:'61'
原长度:1,编码后的长度:2, 编码后是原来的2.00
Base64编码
Base64的算法规则
-
把数据按照字节分为三个字节一组,也就是24bit,如果最后存在不够三个字节为一组,也就是不够24bit的话,就使用0补位
- 由于 编码的时候以6bit为一个编码的单位,所以缺一个字节的话就是24-8=16bit,也就是补2bit的0,那么就得补成18bit,构成整数编码单位。
- 缺两个字节的话就是24-16=8bit,那么就得补成12bit,也就是补4bit的0,构成整数编码单位。
-
每一组按照 以6bit为单位按照下面表格进行编码。如果最后一组只有三个编码单位的长度,那么就在编码的结果最后加上
=
,。如果最后一组只有两个编码单位的长度,那么就在编码的结果最后加上==
Index Binary Char Index Binary Char Index Binary Char Index Binary Char 0 000000 A
16 010000 Q
32 100000 g
48 110000 w
1 000001 B
17 010001 R
33 100001 h
49 110001 x
2 000010 C
18 010010 S
34 100010 i
50 110010 y
3 000011 D
19 010011 T
35 100011 j
51 110011 z
4 000100 E
20 010100 U
36 100100 k
52 110100 0
5 000101 F
21 010101 V
37 100101 l
53 110101 1
6 000110 G
22 010110 W
38 100110 m
54 110110 2
7 000111 H
23 010111 X
39 100111 n
55 110111 3
8 001000 I
24 011000 Y
40 101000 o
56 111000 4
9 001001 J
25 011001 Z
41 101001 p
57 111001 5
10 001010 K
26 011010 a
42 101010 q
58 111010 6
11 001011 L
27 011011 b
43 101011 r
59 111011 7
12 001100 M
28 011100 c
44 101100 s
60 111100 8
13 001101 N
29 011101 d
45 101101 t
61 111101 9
14 001110 O
30 011110 e
46 101110 u
62 111110 +
15 001111 P
31 011111 f
47 101111 v
63 111111 /
Padding =
举例说明
- 最后一组三个字节,不用补位
'abc'
字符串 底层的二进制为 011000010110001001100011
,这是24个bit为一组,以6bit分为四部分为 011000
010110
001001
100011
编码成对应上表的字符 ’ YWJj'
。
byte[] src = "abc".getBytes(StandardCharsets.UTF_8);
byte[] encoded = Base64.encode(src);
System.out.printf("字符串'%s'编码后的字符结果:'%s'%n",new String(src,StandardCharsets.UTF_8),new String(encoded,StandardCharsets.UTF_8));
System.out.printf("原长度:%d,编码后的长度:%d, 编码后是原来的%.2f%n",src.length,encoded.length,(double)(encoded.length)/src.length);
字符串'abc'编码后的字符结果:'YWJj'
原长度:3,编码后的长度:4, 编码后是原来的1.33
-
最后一组只有两个字节,补2bit 0
'ab'
字符串 底层的二进制为0110000101100010
,补位成011000010110001000
,以6bit分为三部分为011000
010110
001000
编码成对应上表的字符 ’YWI'
,因为比一般的少一个编码单位,所以在后面加上一个=
字符,最终的结果就是 ’YWI='
。
byte[] src = "ab".getBytes(StandardCharsets.UTF_8);
byte[] encoded = Base64.encode(src);
System.out.printf("字符串'%s'编码后的字符结果:'%s'%n",new String(src,StandardCharsets.UTF_8),new String(encoded,StandardCharsets.UTF_8));
System.out.printf("原长度:%d,编码后的长度:%d, 编码后是原来的%.2f%n",src.length,encoded.length,(double)(encoded.length)/src.length);
字符串'ab'编码后的字符结果:'YWI='
原长度:2,编码后的长度:4, 编码后是原来的2.00
-
最后一组只有一个字节 补4bit0
'a'
字符串 底层的二进制为01100001
,补位成011000010000
这是24个bit为一组,以6bit分为四部分为011000
010000
编码成对应上表的字符 ’YQ'
,因为比一般的少两个编码单位,所以后面加上两个=
字符,最终的结果就是 ’YQ=='
。
byte[] src = "a".getBytes(StandardCharsets.UTF_8);
byte[] encoded = Base64.encode(src);
System.out.printf("字符串'%s'编码后的字符结果:'%s'%n",new String(src,StandardCharsets.UTF_8),new String(encoded,StandardCharsets.UTF_8));
System.out.printf("原长度:%d,编码后的长度:%d, 编码后是原来的%.2f%n",src.length,encoded.length,(double)(encoded.length)/src.length);
字符串'a'编码后的字符结果:'YQ=='
原长度:1,编码后的长度:4, 编码后是原来的4.00
由于在编码的过程中只有最后一组才有可能存在补位情况,所以我们可以认为 使用base64
编码后数据的体积是原来的1.33
倍
总结
HEX编码的特点是:解码编码速度快但是体积变大了一倍;Base64编码的特点: 体积小,但是由于算法相对复杂所以解码编码速度比较慢。
由于两种编码规则可以是任何二进制的数据编码成字符集可以翻译二进制数据,这样的话我们就轻而易举的把二进制数据打印显示出来。便于我们查看二进制数据。有些网络协议传输只支持文本流的二进制数据传输,所以这时候就可以使用这两种编码。