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吧,沒管它,由於在那以前已經寫入文件了。