BASE64学习小记
Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个“=”。
例:将对ABC进行BASE64编码
首先取ABC对应的ASCII码值。A(65)B(66)C(67)。
再取二进制值A(01000001)B(01000010)C(01000011),然后把这三个字节的二进制码接起来(010000010100001001000011),再以6位为单位分成4个数据块并在最高位填充两个0后形成4个字节的编码后的值(00010000)(00010100)(00001001)(00000011)。蓝色部分为真实数据。再把这四个字节数据转化成10进制数得(16)(20)(19)(3)。
最后根据BASE64给出的64个基本字符表,查出对应的ASCII码字符(Q)(U)(J)(D)。这里的值实际就是数据在字符表中的索引。
1 const char EnBase64Tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678Array+/";
2
3 int EncodeBase64(const unsigned char* pSrc, char* pDst, int nSrcLen, int nMaxLineLen)
4 {
5 unsigned char c1, c2, c3; // 输入缓冲区读出3个字节
6 int nDstLen = 0; // 输出的字符计数
7 int nLineLen = 0; // 输出的行长度计数
8 int nDiv = nSrcLen / 3; // 输入数据长度除以3得到的倍数
9 int nMod = nSrcLen % 3; // 输入数据长度除以3得到的余数
10
11 // 每次取3个字节,编码成4个字符
12 for (int i = 0; i < nDiv; i ++)
13 {
14 // 取3个字节 取24位 3个字节
15 // 取3个字节 取24位 3个字节
16 c1 = *pSrc++;
17 c2 = *pSrc++;
18 c3 = *pSrc++;
19
20 // 编码成4个字符
21 *pDst++ = EnBase64Tab[c1 >> 2]; //C1右移2位 高位补0 取到母表
22 *pDst++ = EnBase64Tab[((c1 << 4) | (c2 >> 4)) & 0x3f]; //C2左移4位 C2右移4位 取非(保留作用) 与003F 屏蔽高2位
23 *pDst++ = EnBase64Tab[((c2 << 2) | (c3 >> 6)) & 0x3f];
24 *pDst++ = EnBase64Tab[c3 & 0x3f];
25 nLineLen += 4;
26 nDstLen += 4;
27
28 // 输出换行?
29 if (nLineLen > nMaxLineLen - 4) //结束
30 {
31 *pDst++ = ’r’;
32 *pDst++ = ’n’;
33 nLineLen = 0;
34 nDstLen += 2;
35 }
36 }
37
38 // 编码余下的字节
39 if (nMod == 1)
40 {
41 c1 = *pSrc++;
42 *pDst++ = EnBase64Tab[(c1 & 0xfc) >> 2]; // 8位 屏蔽低2位
43 *pDst++ = EnBase64Tab[((c1 & 0x03) << 4)]; // 保留低2位
44 *pDst++ = ’=’; // 另外2个字符 用=表示
45 *pDst++ = ’=’;
46 nLineLen += 4;
47 nDstLen += 4;
48 }
49 else if (nMod == 2)
50 {
51 c1 = *pSrc++;
52 c2 = *pSrc++;
53 *pDst++ = EnBase64Tab[(c1 & 0xfc) >> 2];
54
55 *pDst++ = EnBase64Tab[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
56 *pDst++ = EnBase64Tab[((c2 & 0x0f) << 2)];
57 *pDst++ = ’=’;
58 nDstLen += 4;
59 }
60
61 // 输出加个结束符
62 *pDst = ’’;
63
64 return nDstLen;
65 }
66 Base64解码方法中,最简单的也是查表法:将64个可打印字符的值作为索引,查表得到的值(范围为0-63)依次连起来,拼凑成字节形式输出,就得到解码结果。
67
68 const char DeBase64Tab[] =
69 {
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 62, // ’+’
73 0, 0, 0,
74 63, // ’/’
75 52, 53, 54, 55, 56, 57, 58, 5Array, 60, 61, // ’0’-’Array’
76 0, 0, 0, 0, 0, 0, 0,
77 0, 1, 2, 3, 4, 5, 6, 7, 8, Array, 10, 11, 12,
78 13, 14, 15, 16, 17, 18, 1Array, 20, 21, 22, 23, 24, 25, // ’A’-’Z’
79 0, 0, 0, 0, 0, 0,
80 26, 27, 28, 2Array, 30, 31, 32, 33, 34, 35, 36, 37, 38,
81 3Array, 40, 41, 42, 43, 44, 45, 46, 47, 48, 4Array, 50, 51, // ’a’-’z’
82 };
83
84
85
86 void DEbase644(char * string ,char * pch)
87 {
88
89 int len = str.GetLength();
90
91 int i = 0;
92 BYTE b1 ,b2 ,b3 ,b4;
93 char ch;
94 do
95 {
96 //找字符1的位置.
97 b1 = tab.Find((str[i++]));
98
99 //找字符2的位置.
100 b2 = tab.Find((str[i++]));
101
102 ch = (b1 << 2) + (b2 >> 4); //B1 高2位清空 低2位与B2右移后 末4位相与 得到后2位 相与得到第一个字符;
103 //得到此字节..
104 *pch ++ = ch;
105
106 if(i >= len) //超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..
107 break;
108
109 b3 = tab.Find((str[i++])); //取第3个字符..的位置
110
111 //从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..
112
113
114 ch = (b2 <<4) + (b3 >> 2); //B2左移4 清理 补0和B1的尾巴 数数数数 空空空空 B3右移2 空空空空数数数数 相与 得到第二个字符
115 补零
116 *pch ++ = ch;
117 if(i >= len) //超过了..break吧.
118 break;
119 b4 = tab.Find((str[i++])); //找第4个字符..
120 ch = (b3 << 6) + b4; // B3右移6 得到第三个字符的高2位 与上 B4 空空 数数数数数数 得到 第三个字符
121
122 *pch ++ = ch;
123
124 }
125 while(i < len);
126 ////最后加个结束符...
127 *pch =0x00;
128 }
2
3 int EncodeBase64(const unsigned char* pSrc, char* pDst, int nSrcLen, int nMaxLineLen)
4 {
5 unsigned char c1, c2, c3; // 输入缓冲区读出3个字节
6 int nDstLen = 0; // 输出的字符计数
7 int nLineLen = 0; // 输出的行长度计数
8 int nDiv = nSrcLen / 3; // 输入数据长度除以3得到的倍数
9 int nMod = nSrcLen % 3; // 输入数据长度除以3得到的余数
10
11 // 每次取3个字节,编码成4个字符
12 for (int i = 0; i < nDiv; i ++)
13 {
14 // 取3个字节 取24位 3个字节
15 // 取3个字节 取24位 3个字节
16 c1 = *pSrc++;
17 c2 = *pSrc++;
18 c3 = *pSrc++;
19
20 // 编码成4个字符
21 *pDst++ = EnBase64Tab[c1 >> 2]; //C1右移2位 高位补0 取到母表
22 *pDst++ = EnBase64Tab[((c1 << 4) | (c2 >> 4)) & 0x3f]; //C2左移4位 C2右移4位 取非(保留作用) 与003F 屏蔽高2位
23 *pDst++ = EnBase64Tab[((c2 << 2) | (c3 >> 6)) & 0x3f];
24 *pDst++ = EnBase64Tab[c3 & 0x3f];
25 nLineLen += 4;
26 nDstLen += 4;
27
28 // 输出换行?
29 if (nLineLen > nMaxLineLen - 4) //结束
30 {
31 *pDst++ = ’r’;
32 *pDst++ = ’n’;
33 nLineLen = 0;
34 nDstLen += 2;
35 }
36 }
37
38 // 编码余下的字节
39 if (nMod == 1)
40 {
41 c1 = *pSrc++;
42 *pDst++ = EnBase64Tab[(c1 & 0xfc) >> 2]; // 8位 屏蔽低2位
43 *pDst++ = EnBase64Tab[((c1 & 0x03) << 4)]; // 保留低2位
44 *pDst++ = ’=’; // 另外2个字符 用=表示
45 *pDst++ = ’=’;
46 nLineLen += 4;
47 nDstLen += 4;
48 }
49 else if (nMod == 2)
50 {
51 c1 = *pSrc++;
52 c2 = *pSrc++;
53 *pDst++ = EnBase64Tab[(c1 & 0xfc) >> 2];
54
55 *pDst++ = EnBase64Tab[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
56 *pDst++ = EnBase64Tab[((c2 & 0x0f) << 2)];
57 *pDst++ = ’=’;
58 nDstLen += 4;
59 }
60
61 // 输出加个结束符
62 *pDst = ’’;
63
64 return nDstLen;
65 }
66 Base64解码方法中,最简单的也是查表法:将64个可打印字符的值作为索引,查表得到的值(范围为0-63)依次连起来,拼凑成字节形式输出,就得到解码结果。
67
68 const char DeBase64Tab[] =
69 {
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 62, // ’+’
73 0, 0, 0,
74 63, // ’/’
75 52, 53, 54, 55, 56, 57, 58, 5Array, 60, 61, // ’0’-’Array’
76 0, 0, 0, 0, 0, 0, 0,
77 0, 1, 2, 3, 4, 5, 6, 7, 8, Array, 10, 11, 12,
78 13, 14, 15, 16, 17, 18, 1Array, 20, 21, 22, 23, 24, 25, // ’A’-’Z’
79 0, 0, 0, 0, 0, 0,
80 26, 27, 28, 2Array, 30, 31, 32, 33, 34, 35, 36, 37, 38,
81 3Array, 40, 41, 42, 43, 44, 45, 46, 47, 48, 4Array, 50, 51, // ’a’-’z’
82 };
83
84
85
86 void DEbase644(char * string ,char * pch)
87 {
88
89 int len = str.GetLength();
90
91 int i = 0;
92 BYTE b1 ,b2 ,b3 ,b4;
93 char ch;
94 do
95 {
96 //找字符1的位置.
97 b1 = tab.Find((str[i++]));
98
99 //找字符2的位置.
100 b2 = tab.Find((str[i++]));
101
102 ch = (b1 << 2) + (b2 >> 4); //B1 高2位清空 低2位与B2右移后 末4位相与 得到后2位 相与得到第一个字符;
103 //得到此字节..
104 *pch ++ = ch;
105
106 if(i >= len) //超过了..break吧..这是要有这个=号...当=成立的时候.表明已经是最后一个字符了...后面不要处理..
107 break;
108
109 b3 = tab.Find((str[i++])); //取第3个字符..的位置
110
111 //从这里开始判断..因为=号最多有两个...换行是额外加的..所以编码后有效的字符至少为2个..
112
113
114 ch = (b2 <<4) + (b3 >> 2); //B2左移4 清理 补0和B1的尾巴 数数数数 空空空空 B3右移2 空空空空数数数数 相与 得到第二个字符
115 补零
116 *pch ++ = ch;
117 if(i >= len) //超过了..break吧.
118 break;
119 b4 = tab.Find((str[i++])); //找第4个字符..
120 ch = (b3 << 6) + b4; // B3右移6 得到第三个字符的高2位 与上 B4 空空 数数数数数数 得到 第三个字符
121
122 *pch ++ = ch;
123
124 }
125 while(i < len);
126 ////最后加个结束符...
127 *pch =0x00;
128 }