Base64 编解码
Posted 阿Hai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Base64 编解码相关的知识,希望对你有一定的参考价值。
Base64编码简介
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。
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 /
C++实现
#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" int _tmain(int argc, _TCHAR* argv[]) { unsigned char pBuffer[] = "[email protected]#$%^&*()_+{}:\"?></.,;‘[]\\"; //unsigned char pBuffer[] = {‘a‘, ‘b‘, 0, ‘c‘}; 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("[%d]%s\n", j, pOutBuffer); delete[] pOutBuffer; pOutBuffer = NULL; } } system("pause"); return 0; }
以上是关于Base64 编解码的主要内容,如果未能解决你的问题,请参考以下文章