Base64用來將binary的字節序列數據編碼成ASCII字符序列構成的文本。其使用的字符包括大小寫字母各26個,加上10個數字,和加號「+」,斜槓「/」,一共64個字符。另外還使用等號「=」用來做爲後綴。
Base64編碼要求把3個8位字節(3*8=24)轉化爲4個6位的字節(4*6=24),以後在6位的前面補兩個0,造成8位一個字節的形式。若是剩下的字符不足3個字節,則用0填充,最後的輸出字符時使用'='做爲結尾,所以編碼後輸出的文本末尾可能會出現1或2個'='。
爲了保證所輸出的編碼字符都是可讀的,Base64制定了一個編碼表,以便進行統一轉換。編碼表的大小爲2^6=64。ios
Base64編碼表 碼值 字符 碼值 字符 碼值 字符 碼值 字符 0 A 16 Q 32 g 48 w 1 B 17 R 33 h 49 x 2 C 18 S 34 i 50 y 3 D 19 T 35 j 51 z 4 E 20 U 36 k 52 0 5 F 21 V 37 l 53 1 6 G 22 W 38 m 54 2 7 H 23 X 39 n 55 3 8 I 24 Y 40 o 56 4 9 J 25 Z 41 p 57 5 10 K 26 a 42 q 58 6 11 L 27 b 43 r 59 7 12 M 28 c 44 s 60 8 13 N 29 d 45 t 61 9 14 O 30 e 46 u 62 + 15 P 31 f 47 v 63 /
#ifndef __BASE64_UTILS__ #define __BASE64_UTILS__ #include <string> using std::string; class Base64Utils { public: Base64Utils(void); ~Base64Utils(void); /** 將一個字節數組中的數據轉爲一個 base64 格式的數組 */ static string Encode(const unsigned char* pEncodeData, int nLength); /** nLength 爲 0 時返回須要 pOutBuffer 須要分配的大小; 不然解碼數據, 並存入 pOutBuffer 指向的內存中. 返回值: 失敗時返回0. 不然返回反解碼後的字符的個數 */ static int Decode(const string& strBase64, unsigned char* pOutBuffer, int nLength); /** 解析爲一個字符串(由調用者肯定解出的字符中不包含'\0'才能能調用此函數,不然返回的結果可能不是指望的值) */ static string DecodeToString(const string& strBase64); /** 檢查一個字符是不是 base64 編碼的字符 */ static bool CheckBase64(unsigned char bas64Char); protected: template <class T> static T min(T left, T right); }; #endif __BASE64_UTILS__
#include "Base64Utils.h" // Base64 編碼所用的字符, 其順序由 base64 協議規定 static const string BASE64_ENCODE_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // 將 ascii 碼錶中, 對應的 Base64 字符的改爲 Base64 字符表中的索引值, 以便解碼時進行轉行轉換 static const unsigned char BASE64_DECODE_TABLE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, // '+' 0, 0, 0, 63, // '/' 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9' 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z' 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z' }; static const unsigned char BASE64_END_CHARACTER = '='; Base64Utils::Base64Utils(void) { } Base64Utils::~Base64Utils(void) { } template <class T> T Base64Utils::min(T left, T right) { return (left < right) ? left : right; } bool Base64Utils::CheckBase64(unsigned char bas64Char) { return (BASE64_ENCODE_TABLE.find(bas64Char) != -1) ? true : false; } string Base64Utils::Encode(const unsigned char* pEncodeData, int nLength) { string strBase64; int i = 0; for (; i + 2 < nLength; i += 3) { strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> 2) & 0x3f)); strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << 4) | ((pEncodeData[i + 1] >> 4) & 0x0f))); strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + 1] & 0x0f) << 2) | ((pEncodeData[i + 2] >> 6) & 0x03))); strBase64.push_back(BASE64_ENCODE_TABLE.at(pEncodeData[i + 2] & 0x3f)); } if (i < nLength) { strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> 2) & 0x3f)); if (i + 1 < nLength) { strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << 4) | ((pEncodeData[i + 1] >> 4) & 0x0f))); strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + 1] & 0x0f) << 2))); } else { strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << 4))); strBase64.push_back(BASE64_END_CHARACTER); } strBase64.push_back(BASE64_END_CHARACTER); } return strBase64; } int Base64Utils::Decode(const string& strBase64, unsigned char* pOutBuffer, int nLength) { nLength = abs(nLength); int nBase64 = strBase64.length(); /** 不符合 base64 字符串長度要求的字符串, 不是 base64 編碼格式的字符串, 返回 0 */ if ((nBase64 == 0) || ((nBase64 % 4) != 0)) { return 0; } int nNeedSize = nBase64 * 3 / 4; if (strBase64.at(nBase64 - 1) == BASE64_END_CHARACTER) nNeedSize--; if (strBase64.at(nBase64 - 2) == BASE64_END_CHARACTER) nNeedSize--; if (0 == nLength) { return nNeedSize; } nNeedSize = min(nNeedSize, nLength); const int nSizeOfDecode = sizeof(BASE64_DECODE_TABLE); int index = 0; int k = 0; unsigned char byteValue; unsigned char base64Char; unsigned char base64Arr[4] = {0}; for (int i = 0; i < nBase64; i++) { base64Char = strBase64.at(i); if (base64Char == BASE64_END_CHARACTER) // 遇到結速符 { break; } /** 若是 base64字符爲編碼表中只有一個字符, 其解碼後值必定爲 0 不然, 到解碼錶中查找對應的值, 若是找到, 而且值不爲 0, 纔是符合的 base64 編碼的字符. 若是不是 base64 編碼表中的字符, 則解碼失敗, 設置返回值爲 0 */ if (base64Char == BASE64_ENCODE_TABLE.at(0)) { byteValue = 0; } else { if (base64Char < nSizeOfDecode) { byteValue = BASE64_DECODE_TABLE[base64Char]; } if (byteValue == 0) { nNeedSize = 0; break; } } base64Arr[k++] = byteValue; if (k == 4) { if (index >= nNeedSize) break; pOutBuffer[index++] = ((base64Arr[0] & 0x3f) << 2) | ((base64Arr[1] & 0x30) >> 4); if (index >= nNeedSize) break; pOutBuffer[index++] = ((base64Arr[1] & 0x0f) << 4) | ((base64Arr[2] & 0x3c) >> 2); if (index >= nNeedSize) break; pOutBuffer[index++] = ((base64Arr[2] & 0x03) << 6) | ((base64Arr[3] & 0x3f)); k = 0; } } if ((k != 0) && (index < nNeedSize)) { for (; k < 4; k++) { base64Arr[k] = 0; } if (index < nNeedSize) pOutBuffer[index++] = ((base64Arr[0] & 0x3f) << 2) | ((base64Arr[1] & 0x30) >> 4); if (index < nNeedSize) pOutBuffer[index++] = ((base64Arr[1] & 0x0f) << 4) | ((base64Arr[2] & 0x3c) >> 2); if (index < nNeedSize) pOutBuffer[index++] = ((base64Arr[2] & 0x03) << 6) | ((base64Arr[3] & 0x3f)); } return nNeedSize; } string Base64Utils::DecodeToString(const string& strBase64) { string strResult; int nSize = Decode(strBase64, NULL, 0); if (nSize == 0) { return strResult; } unsigned char* pOutBuffer = new unsigned char[nSize + 1]; if (!pOutBuffer) { return strResult; } pOutBuffer[nSize] = 0; nSize = Decode(strBase64, pOutBuffer, nSize); if (nSize != 0) { strResult = reinterpret_cast<char*>(pOutBuffer); } delete[] pOutBuffer; pOutBuffer = NULL; return strResult; }
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <iostream> #include "Base64Utils.h" #define PRINT_BYTE(str, len) {printf("[%03d]", len); for(int t = 0; t < len; t++) printf("%c", str[t]); printf("\n");} int _tmain(int argc, _TCHAR* argv[]) { unsigned char pBuffer[] = "~!@#$%^&\0*(\t)_+{}:\"?></.,;'[]\\"; int nCount = sizeof(pBuffer); printf("count=%d\n", nCount); for (int i = 1; i <= nCount; i++) { string str(&pBuffer[0], &pBuffer[i]); printf("---------- input %d ------------\n", i); printf("%s\n", str.c_str()); string strBase64My = Base64Utils::Encode(pBuffer, i); printf("%s\n", strBase64My.c_str()); int nOutSize = Base64Utils::Decode(strBase64My, NULL, 0); printf("need buffer : %d\n", nOutSize); //printf("decode:%s\n", Base64Utils::DecodeToString(strBase64My).c_str()); //if (strBase64My.length() > 2) //{ // strBase64My.replace(strBase64My.begin() + 2, strBase64My.begin() + 3, 1, ','); // printf("%s\n", strBase64My.c_str()); //} int j = nOutSize; for (; j > 0; j--) { unsigned char* pOutBuffer = new unsigned char[j + 1]; memset(pOutBuffer, 0, j + 1); //pOutBuffer[j] = 0; j = Base64Utils::Decode(strBase64My, pOutBuffer, j); // printf("[%03d]%s\n", j, pOutBuffer); PRINT_BYTE(pOutBuffer, j); delete[] pOutBuffer; pOutBuffer = NULL; } } system("pause"); return 0; }