Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。
可用于网络传输二进制数据(图片,文件...),将二进制转为Base64编码后,可以写入XML,将XML传输到Server端,再进行Base64解码,得到二进制数据。(二进制不能直接写入XML,Base64字符才可以。)
Base64适用于小段内容的编码,比如数字证书签名、Cookie的内容等。
标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。为解决此问题,可采用一种用于URL的改进Base64编码,它在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”。
例子1
索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 |
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 |
例子2
//用更接近于编程的思维来说,编码的过程是这样的:
//第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
//然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位,两者相或(|),或者相加,即获得第二个目标字符。
//再将第二个字符与0x0f(00001111)进行与(&)操作并左移2位,接着第三个字符右移6位,两者相或(|),或者相加,即获得第三个目标字符。
//最后将第三个字符与0x3f(00111111)进行与(&)操作,即获得第四个目标字符。//在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
C++代码实现
特别注意,按位左移和右移,必须是 unsigned char 。可以定义 typedef unsigned char BYTE;
const char* Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxwz0123456789+/"; std::string Base64encode(const unsigned char* buf, unsigned int size) {std::string sBase64;unsigned int i;for (i = 0; i < size/3*3; i += 3){sBase64 += Base64[buf[i] >> 2];sBase64 += Base64[(buf[i]<<4 | buf[i+1]>>4) & 0x3f];sBase64 += Base64[(buf[i+1]<<2 | buf[i+2]>>6) & 0x3f];sBase64 += Base64[buf[i+2] & 0x3f];}if (size % 3 == 1){sBase64 += Base64[buf[i] >> 2];sBase64 += Base64[buf[i]<<4 & 0x3f];sBase64 += '=';sBase64 += '=';}else if (size % 3 == 2){sBase64 += Base64[buf[i] >> 2];sBase64 += Base64[(buf[i]<<4 | buf[i+1]>>4) & 0x3f];sBase64 += Base64[buf[i+1]<<2 & 0x3f];sBase64 += '=';}return sBase64; } std::string Base64decode(std::string sBase64) {std::string sRet;unsigned int nLen = sBase64.size();//nLen一定是4的倍数unsigned char* a = new unsigned char[nLen];int count = 0; // the number of '='.for (unsigned i = 0; i < nLen; ++i){if (sBase64[i] >= 'A' && sBase64[i] <= 'Z')a[i] = sBase64[i] - 'A';else if (sBase64[i] >= 'a' && sBase64[i] <= 'z')a[i] = sBase64[i] - 'a' + 26;else if (sBase64[i] >= '0' && sBase64[i] <= '9')a[i] = sBase64[i] - '0' + 52;else if ('+' == sBase64[i])a[i] = 62;else if ('/' == sBase64[i])a[i] = 63;else if ('=' == sBase64[i]){a[i] = 0;count++;}}sRet.resize(nLen/4*3);unsigned j = 0;for (unsigned i = 0; i < nLen; i += 4){sRet[j++] = a[i]<<2 | a[i+1]>>4;sRet[j++] = a[i+1]<<4 | a[i+2]>>2;sRet[j++] = a[i+2]<<6 | a[i+3];}delete[] a;assert(j == nLen / 4 * 3);if (count)sRet.resize(sRet.size() - count);return sRet; }int main() {//std::string s("i\xb7\x1d\xfb\xef\xffi");//-> abcd++//aQ==//std::string s("\x00\x3f\xbf\xd7m",5);//-> AD+/120=std::string s("abcde"); // -> YWJjZGU=std::string r = Base64encode((const unsigned char*)s.c_str(), s.size());std::string sRet = Base64decode(r);return 0; }
方法2:
std::string Base64encode(const unsigned char* buf, unsigned int size) {//方法二typedef unsigned char BYTE;std::string sBase64;std::basic_string<BYTE> s(buf, buf+size);unsigned count = 0;//不足3的倍数,补 \0 的个数,即编码后“=”个数。if (size % 3 == 1){s.push_back('\0');s.push_back('\0');count = 2;}else if (size % 3 == 2){s.push_back('\0');count = 1;}sBase64.resize((size+count)/3*4);//sBase64的大小一定是4的倍数。unsigned j = 0;for (unsigned i = 0; i < s.size(); i += 3){sBase64[j++] = Base64[s[i] >> 2];sBase64[j++] = Base64[(s[i]<<4 | s[i+1]>>4) & 0x3f];sBase64[j++] = Base64[(s[i+1]<<2 | s[i+2]>>6) & 0x3f];sBase64[j++] = Base64[s[i+2] & 0x3f];}while (count--)//此时 j = (size+count)/3*4sBase64[--j] = '=';return sBase64; }
在线base编码解码?