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 }
关于接口定义

 

posted @ 2018-09-29 17:37  心中的阿哲  阅读(1564)  评论(0编辑  收藏  举报