闲来无事用C++写了一个Base64编码和解码的小程序
Base64.h
#ifndef _BASE64_H
#define _BASE64_H
/*
Base64是一种基于64个可打印字符来表示二进制数据的表示方法,从本质上看Base64编码就是将三字节转四字节。
如果数据的长度不是3的整数倍,就要在后面补0再计算,每补2个0就再Base64串后加上1个‘=’。
Base64的不足之处:
标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,
而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充'='号,
并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,
避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
*/
#include <string>
static inline bool IsBase64Char(unsigned char c);
std::string Base64Encode(const char* bytes_to_encode, unsigned int in_len);
std::string Base64Decode(const std::string encoded_str, unsigned int in_len);
static const std::string g_base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#endif
Base64.cpp
#include "Base64.h"
static inline bool IsBase64Char(unsigned char ch)
{
if ((ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| (ch >= '0' && ch <= '9')
|| (ch == '+')
|| (ch == '/'))
{
return true;
}
else
{
return false;
}
}
std::string Base64Encode(const char* bytes_to_encode, unsigned int in_len)
{
std::string ret_str;
int i = 0, j = 0;
unsigned char char_array_3bytes[3] = { 0 };
unsigned char char_array_4bytes[4] = { 0 };
while (in_len > 0 )
{
char_array_3bytes[i++] = *(bytes_to_encode++);
if (i == 3) //先将3位扩展成4位
{
char_array_4bytes[0] = (char_array_3bytes[0] & 0xfc) >> 2;
char_array_4bytes[1] = ((char_array_3bytes[0] & 0x03) << 4) + ((char_array_3bytes[1] & 0xf0) >> 4);
char_array_4bytes[2] = ((char_array_3bytes[1] & 0x0f) << 2) + ((char_array_3bytes[2] & 0xc0) >> 6);
char_array_4bytes[3] = char_array_3bytes[2] & 0x3f;
for (i = 0; i < 4; i++)
{
ret_str += g_base64_chars[char_array_4bytes[i]];
}
i = 0;
}
in_len--;
}
if (i != 0)
{
for (j = i; j < 3; j++)
{
char_array_3bytes[j] = '\0';
}
// 清零
char_array_4bytes[0] = (char_array_3bytes[0] & 0xfc) >> 2;
char_array_4bytes[1] = ((char_array_3bytes[0] & 0x03) << 4) + ((char_array_3bytes[1] & 0xf0) >> 4);
char_array_4bytes[2] = ((char_array_3bytes[1] & 0x0f) << 2) + ((char_array_3bytes[2] & 0xc0) >> 6);
char_array_4bytes[3] = char_array_3bytes[2] & 0x3f;
for (j = 0; (j < i + 1); j++) //得到对应的Base64编码值
{
ret_str += g_base64_chars[char_array_4bytes[j]];
}
while (i < 3) //不足的时候补上'='
{
ret_str += '=';
i++;
}
}
return ret_str;
}
std::string Base64Decode(const std::string encoded_str, unsigned int in_len)
{
int i = 0, j = 0, k = 0;
unsigned char char_array_4bytes[4] = { 0 };
unsigned char char_array_3bytes[3] = { 0 };
std::string ret_str;
while ((in_len > 0)
&& (encoded_str[k] != '=')
&& IsBase64Char(encoded_str[k]))
{
char_array_4bytes[i++] = encoded_str[k++];
if (i == 4)
{
for (i = 0; i < 4; i++)
{
char_array_4bytes[i] = g_base64_chars.find(char_array_4bytes[i]);
}
char_array_3bytes[0] = (char_array_4bytes[0] << 2) + ((char_array_4bytes[1] & 0x30) >> 4);
char_array_3bytes[1] = ((char_array_4bytes[1] & 0xf) << 4) + ((char_array_4bytes[2] & 0x3c) >> 2);
char_array_3bytes[2] = ((char_array_4bytes[2] & 0x3) << 6) + char_array_4bytes[3];
for (i = 0; (i < 3); i++)
{
ret_str += char_array_3bytes[i];
}
i = 0;
}
in_len--;
}
if (i != 0)
{
for (j = i; j < 4; j++)
{
char_array_4bytes[j] = 0;
}
for (j = 0; j < 4; j++)
{
char_array_4bytes[j] = g_base64_chars.find(char_array_4bytes[j]);
}
char_array_3bytes[0] = (char_array_4bytes[0] << 2) + ((char_array_4bytes[1] & 0x30) >> 4);
char_array_3bytes[1] = ((char_array_4bytes[1] & 0xf) << 4) + ((char_array_4bytes[2] & 0x3c) >> 2);
char_array_3bytes[2] = ((char_array_4bytes[2] & 0x3) << 6) + char_array_4bytes[3];
for (j = 0; (j < i - 1); j++)
{
ret_str += char_array_3bytes[j];
}
}
return ret_str;
}
MainTest.cpp
#include <iostream>
#include "Base64.h"
int main()
{
const std::string srcString = "abchgy78huy~!@#$%Base64测试函数^&*()_+`-=,./;'[]<>?:{}";
std::string encoded = Base64Encode(srcString.c_str(), srcString.length());
std::string decoded = Base64Decode(encoded, encoded.length());
std::cout << "srcString: " << srcString << std::endl;
std::cout << "encoded: " << encoded << std::endl;
std::cout << "decoded: " << decoded << std::endl;
return 0;
}