base64编码和解码
一、base64是什么?
由26个大小写英文字母,0~9的10个数字和两个字符(斜杠'/'与加号'+')组成。 正因为它们都是可见的,所以被用来对传递在前端和后台之间的信息(尤其是不可见的)进行编码,比如图片,由ASCII码组成,其中含有控制字符,是不可见的。
二、怎么编码?
一个ASCII码占8位二进制,一个base64码占6位二进制(因为2的6次方是64),所以,三个ASCII码可以换成四个base64码,如下图:
ASCII码 |
‘O’ |
‘N’ |
‘E’ |
|||
十进制 |
79 |
78 |
69 |
|||
二进制(8位) |
01001111 |
01001110 |
01000101 |
|||
二进制(6位) |
010011 |
110100 |
111001 |
000101 |
||
十进制 |
19 |
52 |
57 |
5 |
||
BASE64码 |
‘T’ |
‘0’ |
‘5’ |
‘F’ |
“ONE”转换成了“T05F”
当然,如果剩下了2个或者1个ASCII码,则需要用'='补充,比如,剩下1个ASCII码,
ASCII码 |
‘O’ |
空 |
空 |
||
十进制 |
79 |
空 |
空 |
||
二进制(8位) |
01001111 |
空 |
空 |
||
二进制(6位) |
010011 |
11 0000 |
空 |
空 |
|
十进制 |
19 |
48 |
空 |
空 |
|
BASE64码 |
‘T’ |
‘w’ |
‘=’ |
‘=’ |
“O”转换成“Tw==”, 用'='凑成三个字节,即转换成二进制是24位。
三、怎么解码?
解码就是上面的逆过程,只是不考虑等号‘=’。
四、我的代码
头文件
/* 这是一份关于函数返回值定义的头文件。 */ #ifndef _GENERAL_H_ #define _GENERAL_H_ /* 附加类型 */ typedef unsigned char uChar; typedef unsigned int uInt; /* 返回状态值 */ #define STATUS int #define OK 6 #define ERROR -6 #endif
/* 这是一份关于函数返回值定义的头文件。 */ #ifndef _GENERAL_H_ #define _GENERAL_H_ /* 附加类型 */ typedef unsigned char uChar; typedef unsigned int uInt; /* 返回状态值 */ #define STATUS int #define OK 6 #define ERROR
/* 这是一份关于Base64码和ASCII码相互转换的接口声明文件 */ #ifndef _BASE64_H_ #define _BASE64_H_ #include "general.h" /* ** 把base64码转换为ASCII码。 ** ** base64 -- 目标串 ** asciip -- 返回结果串 ** asciiLenp -- 返回结果串的长度 ** 返回值,如果转换成功返回OK;否则返回ERROR。 */ STATUS Base64ToASCII(char const * base64, uChar ** const asciip, uInt * const asciiLenp); /* ** 把ASCII码转换为base64码。 ** ** ascii -- 目标串 ** asciiLen -- 目标串的长度 ** base64p -- 返回结果串 ** 返回值,如果转换成功返回OK;否则返回ERROR。 */ STATUS ASCIIToBase64(uChar const * ascii, uInt asciiLen, char ** const base64p); #endif
源文件
1 /* 这是一份关于Base64码和ASCII码相互转换的接口定义文件 */ 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <math.h> 6 #include "general.h" 7 #include "base64.h" 8 9 #define EQUAL 64 //base64码的等号下标 10 static char const base64Tray[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; //存放base64码 11 static char const *binaries [] = { //存放base64码的二进制形式 12 "000000", "000001", "000010", "000011", "000100", "000101", "000110", "000111", 13 "001000", "001001", "001010", "001011", "001100", "001101", "001110", "001111", 14 "010000", "010001", "010010", "010011", "010100", "010101", "010110", "010111", 15 "011000", "011001", "011010", "011011", "011100", "011101", "011110", "011111", 16 "100000", "100001", "100010", "100011", "100100", "100101", "100110", "100111", 17 "101000", "101001", "101010", "101011", "101100", "101101", "101110", "101111", 18 "110000", "110001", "110010", "110011", "110100", "110101", "110110", "110111", 19 "111000", "111001", "111010", "111011", "111100", "111101", "111110", "111111", 20 }; 21 22 /* 23 ** 把8位二进制转换为一个十进制 24 ** 25 ** buffer -- 指向待转换的8位二进制字符串 26 ** valuep -- 指向存放十进制的地址 27 ** 返回值,空。 28 */ 29 static void 30 ConvertItToASCII(char const *buffer, uChar * const valuep) 31 { 32 uChar value; 33 uInt temp = 0; 34 int i; 35 36 for(i = 0; i < 8; i ++) 37 { 38 temp += (buffer [i] - '0') * (int)pow(2, 7 - i); 39 } 40 value = (uChar)temp; 41 *valuep = value; 42 } 43 44 /* 45 ** 把6位二进制转换为一个十进制 46 ** 47 ** buffer -- 指向待转换的6位二进制字符串 48 ** valuep -- 返回转换的十进制 49 ** 返回值,空。 50 */ 51 static void 52 ConvertItToBase64(char const *buffer, int * const valuep) 53 { 54 int value = 0; 55 int i; 56 57 for(i = 0; i < 6; i ++) 58 { 59 value += (buffer [i] - '0') * (int)pow(2, 5 - i); 60 } 61 *valuep = value; 62 } 63 64 /* 65 ** 把一个ASCII码转换为8位二进制串 66 ** 67 ** value -- 待转换的整数 68 ** binaryp -- 返回8位二进制串 69 ** 返回值,空。 70 */ 71 static void 72 ConvertIt(uChar value, char ** const binaryp) 73 { 74 char *binary = NULL; 75 int count = 8; 76 77 binary = (char *)malloc(9 * sizeof(char)); 78 if(binary == NULL) 79 { 80 fprintf(stdout, "Error at ConvertIt(): 内存不足\n"); 81 exit(EXIT_FAILURE); 82 } 83 84 binary [count] = '\0'; 85 while(value != 0) 86 { 87 binary [count - 1] = value % 2 + '0'; 88 count --; 89 value /= 2; 90 } 91 while(count != 0) 92 { 93 binary [count - 1] = value + '0'; 94 count --; 95 } 96 97 *binaryp = binary; 98 } 99 100 /* 101 ** 把base64码转换为ASCII码。 102 ** 103 ** base64 -- 目标串 104 ** asciip -- 返回结果串 105 ** asciiLenp -- 返回结果串的长度 106 ** 返回值,如果转换成功返回OK;否则返回ERROR。 107 */ 108 STATUS 109 Base64ToASCII(char const * base64, uChar ** const asciip, uInt * const asciiLenp) 110 { 111 uChar *ascii = NULL; 112 uChar v; 113 int base64Len = 0; 114 int asciiLen = 0; 115 char const *p = NULL; 116 char ch; 117 char buffer [25] = ""; //存放4个base64码的二进制 118 int index; 119 int count; 120 int i; 121 122 /* 检查参数是否有效 */ 123 if(base64 == NULL) 124 { 125 fprintf(stdout, "Error at Base64ToASCII(): 传递给函数Base64ToASCII()的参数base64不能为空。\n"); 126 return ERROR; 127 } 128 if(asciip == NULL) 129 { 130 fprintf(stdout, "Error at Base64ToASCII(): 传递给函数Base64ToASCII()的参数asciip不能为空。\n"); 131 return ERROR; 132 } 133 134 135 /* 申请一段足够大的内存result */ 136 asciiLen = base64Len = strlen(base64); 137 while(asciiLen * 6 % 8 != 0) 138 { 139 asciiLen ++; 140 }asciiLen = asciiLen * 6 / 8; 141 142 ascii = (uChar *)malloc((asciiLen + 1) * sizeof(uChar)); 143 if(ascii == NULL) 144 { 145 fprintf(stdout, "Error at Base64ToASCII(): 内存不足。\n"); 146 exit(EXIT_FAILURE); 147 } 148 memset(ascii, 0, (asciiLen + 1) * sizeof(uChar)); 149 150 151 /* 把base64码先转换为二进制,再转换为ASCII码 */ 152 153 i = 0; // result的下标序号 154 count = 0; // buffer的计数器 155 p = base64; 156 while((ch = *p) != '=' && ch != '\0') 157 { 158 index = strchr(base64Tray, ch) - base64Tray; 159 strcpy(buffer + count * 6, binaries [index]); 160 count ++; 161 if(count == 4) 162 { 163 count --; 164 index = 0; 165 do{ 166 ConvertItToASCII(buffer + index * 8, &v); 167 index ++; 168 ascii [i ++] = v; 169 count --; 170 }while 171 (count != 0); 172 } 173 p ++; 174 } 175 if(count != 0) 176 { 177 int bufferLen = strlen(buffer); 178 char *q = strchr(buffer, 0); 179 180 while(bufferLen % 8 != 0) 181 { 182 *q = '0'; 183 q ++; 184 bufferLen ++; 185 } 186 *q = '\0'; 187 188 q = buffer; 189 while((ch = *q) != '\0') 190 { 191 ConvertItToASCII(q, &v); 192 ascii [i ++] = v; 193 count --; 194 q += 8; 195 } 196 } 197 198 /* 返回结果 */ 199 *asciip = ascii; 200 *asciiLenp = asciiLen; 201 return OK; 202 } 203 204 /* 205 ** 把ASCII码转换为base64码。 206 ** 207 ** ascii -- 目标串 208 ** asciiLen -- 目标串的长度 209 ** base64p -- 返回结果串 210 ** 返回值,如果转换成功返回OK;否则返回ERROR。 211 */ 212 STATUS 213 ASCIIToBase64(uChar const * ascii, uInt asciiLen, char ** const base64p) 214 { 215 char *base64 = NULL; 216 uInt base64Len; //base64总长度 217 int left; //base64的余长 218 int equalNum; //末尾要添加的'='数目 219 char buffer [25] = ""; //存放24位二进制 220 char *p = NULL; 221 char *temp = ""; //存放8位二进制 222 int value; 223 int count; 224 int i; 225 int base64Index; 226 227 /* 检查参数是否有效 */ 228 if(ascii == NULL) 229 { 230 fprintf(stdout, "Error at ASCIIToBase64(): 传递给函数ASCIIToBase64()的参数ascii不能为空。\n"); 231 return ERROR; 232 } 233 if(base64p == NULL) 234 { 235 fprintf(stdout, "Error at ASCIIToBase64(): 传递给函数ASCIIToBase64()的参数base64不能为空。\n"); 236 return ERROR; 237 } 238 239 /* 申请足够大的内存用于存放base64码 */ 240 left = asciiLen * 8 % 6; 241 equalNum = asciiLen * 8 % 24; 242 while(left % 6 != 0) 243 { 244 left ++; 245 }left /= 6; 246 if(left != 0) 247 { 248 while(equalNum % 8 != 0) 249 { 250 equalNum ++; 251 }equalNum = (24 - equalNum) /8; 252 } 253 254 base64Len = asciiLen * 8 / 6 + left + equalNum; //base64的总长度 255 256 base64 = (char *)malloc((base64Len + 1) * sizeof(char)); 257 if(base64 == NULL) 258 { 259 fprintf(stdout, "Error at ASCIIToBase64(): 内存不足。\n"); 260 exit(EXIT_FAILURE); 261 } 262 memset(base64, 0, (base64Len + 1) * sizeof(char)); 263 264 /* 转换ascii码为base64码,并存入base64 */ 265 for(base64Index = count = i = 0; i < (int)asciiLen; i ++) 266 { 267 ConvertIt(ascii [i], &temp); 268 strcpy(buffer + count * 8, temp); 269 free(temp); 270 temp = NULL; 271 count ++; 272 if(count == 3) 273 { 274 count ++; 275 p = buffer; 276 do 277 { 278 ConvertItToBase64(p, &value); 279 base64 [base64Index ++] = base64Tray [value]; 280 p += 6; 281 count --; 282 }while 283 (count != 0); 284 } 285 } 286 if(count != 0) //结尾处理 287 { 288 int bufferLen = strlen(buffer); 289 char *q = strchr(buffer, '\0'); 290 291 while(bufferLen % 6 != 0) 292 { 293 *q = '0'; 294 q ++; 295 bufferLen ++; 296 } 297 *q = '\0'; 298 299 count ++; 300 q = buffer; 301 do 302 { 303 ConvertItToBase64(q, &value); 304 base64 [base64Index ++] = base64Tray [value]; 305 q += 6; 306 count --; 307 }while 308 (count != 0); 309 } 310 while(equalNum --) //用等号补齐 311 { 312 base64 [base64Index ++] = base64Tray [EQUAL]; 313 } 314 315 /* 返回结果 */ 316 *base64p = base64; 317 return OK; 318 }