Base64被普遍用于xml类型的文档中,经过实现编码和译码,能够练习一下c++c++
首先,咱们要知道什么是Base64编码。它是把二进制文件存储成为文本文件后的文件的编码,它是64位进制的编码,因此对于0至63的数字咱们都须要一个字符来表示。Base64的字符集很简单,0-25 这26位是[A-Z] 26-51这26位是[a-z],52-61这十位是[0-9] 62位是+ 63位是/ 这里咱们添加一个64号位=。 =号做用很大,一会再说。数据结构
Base64的编码过程是这样的,首先读取一个二进制文件,而后,把每三个byte取出来,对于这三个byte如何处理呢?3个byte即3*8=24 bit 咱们把每6个bits拿出来,共4*6 = 24,因此有4个6位的二进制数,咱们在这4个数的首位均补上两个0,这样能够获得4个byte,咱们把文件的长度增长了三分之一左右,可是让全部的byte所表示的数字均不超过63,咱们这时使用Base64的字符集把数字映射成字符,而后就成为了文本。若是它的字节数不是3的倍数呢,咱们能够在它们占位的地方使用=函数
这里咱们说编码过程是为了解码,若是解码作出来了其实编码很简单。编码
由于c++中cout很好用,因此用的是c++语言,可是里面除去cout部分都是使用c的库和函数,因此能够说这个是c/c++通用的。code
咱们要解码,首先,咱们要把每4个字符拿出来,变成4个6bit的值。由于源文件为文本文件,目标文件是二进制文件,因此在读取的时候使用fgetc,写入时使用fwritexml
const int map_length = 65; struct bits { unsigned a:6; unsigned b:6; unsigned c:6; unsigned d:6; }; const char map[map_length] = { 'A','B','C','D','E', 'F','G','H','I','J', 'K','L','M','N','O', 'P','Q','R','S','T', 'U','V','W','X','Y', 'Z','a','b','c','d', 'e','f','g','h','i', 'j','k','l','m','n', 'o','p','q','r','s', 't','u','v','w','x', 'y','z','0','1','2', '3','4','5','6','7', '8','9','+','/','=', };
这个是映射表,以及存储4个6bit的数据结构。索引
int getIndex(char c){ for(int i=0; i<map_length; i++){ if(map[i] == c) { return i; } } cout << "invalid char!!" << endl; exit(1); }
经过字符查找索引数字。
int main() { cout << "Hello world!" << endl; /* 下行代码结果为 1,因此char是1byte的 cout << sizeof(char) << endl;*/ FILE * file = 0, * wfile = 0; /* 把从mht文件中找到的base64编码复制到一个文本文件中 * 是一个png文件,取名为a.png.base64,只读打开 * 再打开一个输出文件result.png 二进制写入方式 * i是在循环中计数用的 * block用来一次性表示3个byte块 * buf用来存储拿到的四个整数 * tmp是当前拿到的字符 */ file = fopen("a.png.base64","r"); wfile = fopen("result.png", "wb"); int i=0; bits block; int buf[4]; char tmp; if(file == 0 || wfile == 0) { cout << "Error opening file!" << endl; exit(1); } // 获取字符,输出到屏幕,忽略掉\n并写入文件中 // 这里要注意,实际中block内部存储的顺序:dcba // 这里要倒置两次 while(!feof(file)) { tmp = fgetc(file); if(tmp != '\n') { buf[i % 4] = getIndex(tmp); i++; if(i % 4 == 0) { block.a = buf[3]; block.b = buf[2]; block.c = buf[1]; block.d = buf[0]; char *tmp; char chs[3]; tmp = (char *)█ chs[0] = tmp[2]; chs[1] = tmp[1]; chs[2] = tmp[0]; fwrite(chs, 1, 3, wfile); } cout << tmp; //fputc(tmp, wfile); } } fclose(file); fclose(wfile); cout << endl; //没什么做用,表示结束了,打印下好看 for(int i=0; i<65; i++) { cout << "="; } return 0; }有一点不足,文件最后会出现一次invalid char,多是文件结束符eof吧,没管它,由于在那以前已经写入文件了。