admin 管理员组文章数量: 887016
2024年2月24日发(作者:request动词用法)
Base64编解码
一、编码原理
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。编码后的数据比原来的数据略长,是原来的4/3倍。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中而不同(Base64de 编码表如下所示)。Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email,email via MIME, 在XML中存储复杂数据.
Base64编码表
Value
Char
Value
Char
Value
Char
Value
Char
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
A
B
C
D
E
F
G
I
J
K
L
M
N
O
P
16
17
18
19
20
21
22
24
25
26
27
28
29
30
31
Q
R
S
T
U
V
W
Y
Z
a
b
c
d
e
f
32
33
34
35
36
37
38
40
41
42
43
44
45
46
47
g
h
i
j
k
l
m
o
p
q
r
s
t
u
v
48
49
50
51
52
53
54
56
57
58
59
60
61
62
63
w
x
y
z
0
1
2
3
4
5
6
7
8
9
+
/
H
23
X
39
n
55
二、编码流程
步骤1:将要编码的所有字符都转化成对应的ASCII码。
步骤2:将所有的ASCII码转换成对应的8位长的二进制数。
步骤3:将所得的二进制数从高位到低位开始分成6位一组,最后一组不足六的则补充0
步骤4:将每组二进制数转换成十进制数,然后对照base64的编码表查找得到相应的编码。
注意:1、 要求被编码字符是8bit的,所以须在ASCII编码范围内,u0000-u00ff,中文就不行。
2、如果被编码的字符串中字符的个数为3的倍数,按照上面的步骤即可得到正确的base64编码。但是如果不是3的倍数则要分情况讨论。如果是3的倍数余1,则要在编好的码字后面加上两个“=”,如果是3的倍数余2,这要在编好的码字后面加上一个“=”。(例如w的base64编码为dw==,w1的base64编码为dzE=)
下面我们来对具体的字符串进行编码举例,以便更好的理解编码流程:
编码「Man」
文本
ASCII编码
索引
Base64编码
M
77
19
T
22
W
a
97
5
F
n
110
46
u
二进制位 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
在此例中,Base64算法将三个字符编码为4个字符
特殊情况
文本(1 Byte) A
二进制位
Base64编码
文本(2 Byte)
二进制位
Base64编码
A的编码为QQ= =
BC的编码为QkM=
0 1 0 0 0 0 0 1
Q
B
Q
C
二进制位(補0) 0 1 0 0 0 0 0 1 0 0 0 0
0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 x x x x x x
Q k M
二进制位(補0) 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 x x x x x x
三、核心算法程序
算法的基本原理如下:由于每次转换都需要6个bit,而这6个bit可能都来自一个字节,也可以来自前后相临的两个字节。定义两个变量:prevByteBitCount和nextByteBitCount,这两个变量分别表述从前一个和后一个节字取得的bit数。如果prevByteBitCount为0,表示6个bit全部来自下一个字节的高6位。如果nextByteBitCount = 0,表示6个bit全部来自前一个字节的低6位。最后通过适当的移位获得所需要的6个bit,再在上面的base64编码表中查找相应的字符。算法的实现代码如下:
public static String encoder(byte[] bytes)
{
StringBuilder result = new StringBuilder();
String base64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
// prevByteBitCount表示从前一个字节取得的bit数,nextByteBitCount表示从后一个字节取得的bit数
int prevByteBitCount = 0, nextByteBitCount = 6;
// i表示当前的数组索引,n表示已经处理的位数
int i = 0, n = 0;
// byteCount表示总的位数
int byteCount = 8 * ;
byte b = 0;
while (true)
{
// 处理从前后两个字节取得位数的情况
if (prevByteBitCount > 0 && nextByteBitCount > 0)
{
// 将前一个字节的低位向左移nextByteBitCount个bit,并使下一个字节的高位(nextByteBitCount指定的位数)右移到字节的最低位,
// 然后将两个位移结果进行逻辑或,也就是将从前一个字节和后一个字节取得的相应的bit合并为一个字节的低位
b = (byte) (((0xff & bytes[i]) << nextByteBitCount) | ((0xff & bytes[i + 1]) >> (8
- nextByteBitCount)));
// 将逻辑或后的结果的最高两个bit置成0
b = (byte) (b & 0x3f);
prevByteBitCount = 8 - nextByteBitCount;
nextByteBitCount = 6 - prevByteBitCount;
}
// 处理从后一个字节取得高6位的情况
else if (prevByteBitCount == 0)
{
// 后一个字节的高6位右移动低6位
b = (byte) ((0xff & bytes[i]) >> (8 - nextByteBitCount));
// 处理后面的位时,就是从前一个字节取2个bit,从后一个字字取4个bit
prevByteBitCount = 2;
nextByteBitCount = 4;
}
// 处理从前一个字节取得低6位的情况
else if (nextByteBitCount == 0)
{
// 将前一个字节的最高两个bit置成0
b = (byte) (0x3f & bytes[i]);
// 处理后面的位时,从后一个字节取6个bit
prevByteBitCount = 0;
nextByteBitCount = 6;
}
((b));
n += 6;
i = n / 8;
int remainBitCount = byteCount - n;
if (remainBitCount < 6)
{
// 将剩余的bit补0后,仍然需要在base64编码表中查找相应的字符,并添加到结果字符串的最后
if (remainBitCount > 0)
{
b = bytes[ - 1];
b = (byte) (0x3f & (b << (6 - remainBitCount)));
((b));
}
break;
}
}
// 如果总bit数除3的余数为1,加一个“=”,为2,加两个“=”
n = byteCount % 3;
for (i = 0; i < n; i++)
("=");
return ng();
}
对于程序的理解:这个程序应该只是总程序的一部分,它主要实现了对二进
制代码分成以6位长为一组的分组,考虑了位数不足的情况,个人觉得这个是程序中的难点,所以就把它放进来了。在这个程序中直接调用了查找base64编码表这个函数。
四、解码
Base64的解码原理很简单,其实就是编码的逆过程。
步骤1:将所给的字符在base64编码表中查到相应的数值
步骤2:将数值均转化成6位的二进制数
步骤3:将二进制数从高位到低位的顺序,以8为长度分组。(若所给的base64码结尾没有“=”的情况,即字符数正好是4的倍数。如果有“=”,这不是8的倍数,此时需要将最后的两位或者四位省去。这就可能导致不同的符号可以解码出相同的编码,如下面所示的例子。)
步骤4:将每组的二进制数转换成对应的ASCII代码。这样就可以得到解码后的字符。
举例说明:
解码er==
Base64编码表中对应的值为30 43
每个化成对应6为二进制位 011110 101011
以8位长为一组,多余省去,这可得01111010
则其ASCII码数值为7Ah,对应字符为Z
eq==解码所得结果也为Z。
注意:如果在步骤三中所得的数在ASCII码表中找不到对应数,则会出现解码错误。例如erYT解码得到就是Z!!(这是我在网上的base64解码器中实验得到的结果)
五、感悟
我们觉得Base64的编码、解码原理很简单,但是它的应用范围挺广的,而且它的源代码对于我们来说也不简单(有的部分知道怎么回事,但是不知道怎么用程序来实现)。在这次找编解码的过程中,我们受益良多。一开始找的都是那些很大的音频、视频编解码,像ACC、OGG、H.264等等,基本上都看不懂,只能知道它是干什么的。后来又找到了曼彻斯特编码、AMI编解码,结果有人已经做了,所以最后我们选了Base64编解码。所以这次作业让我们了解了好多以前完全没有接触过的代码,收获颇丰。
版权声明:本文标题:Base64编解码 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1708727557h529928.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论