zoukankan      html  css  js  c++  java
  • 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(): 内存不足
    ");
     81         exit(EXIT_FAILURE);
     82     }
     83     
     84     binary [count] = '';
     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不能为空。
    ");
    126         return ERROR;
    127     }
    128     if(asciip == NULL)
    129     {
    130         fprintf(stdout, "Error at Base64ToASCII(): 传递给函数Base64ToASCII()的参数asciip不能为空。
    ");
    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(): 内存不足。
    ");
    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 != '')
    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 = '';
    187 
    188         q = buffer;
    189         while((ch = *q) != '')
    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不能为空。
    ");
    231         return ERROR;
    232     }
    233     if(base64p == NULL)
    234     {
    235         fprintf(stdout, "Error at ASCIIToBase64(): 传递给函数ASCIIToBase64()的参数base64不能为空。
    ");
    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(): 内存不足。
    ");
    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, '');
    290 
    291         while(bufferLen % 6 != 0)
    292         {
    293             *q = '0';
    294             q ++;
    295             bufferLen ++;
    296         }
    297         *q = '';
    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 }
    关于接口定义
  • 相关阅读:
    在Win7 x64环境中将World Wind Java SDK 2.1.0嵌入到Eclipse中的方法
    WW中文地名标注:输出*.wwp和*.wpl文件
    [转]Microsoft Robotics Studio:微软仿真机器人集成开发环境,简称MSRS
    C#中定义类时关于CLSCompliant属性的声明
    Android Studio中使用Java+OpenGL ES创建Android项目
    [转]使用Unity进行3D开发的思路和主要技术优势
    在C++中实现委托事件的方法
    VS2008新建MFC程序时提示:当前页面的脚本发送错误 不是有效的Win32应用程序的解决办法
    [Web 前端] mockjs让前端开发独立于后端
    [Web 前端] 如何构建React+Mobx+Superagent的完整框架
  • 原文地址:https://www.cnblogs.com/the-one/p/9724970.html
Copyright © 2011-2022 走看看