Base64的编码与解码

代码呈现

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>

using namespace std;


class Base64
{

    public: 

        int Encode(string &s);
        int EncodeWeb(string &s);
		int Decode(string &s);
		int DecodeWeb(string &s);

		vector<string> Split(string aimString);

    private:

        const unsigned char Base64EncodeMap[64] =
        {
            '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', '+', '/'
        };

		const unsigned char Base64DecodeMap[256] =
		{
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F,
			0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
			0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
			0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
			0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
			0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
			0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
			0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
			0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
			0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
		};
        
        string EncodeEach(char buffer[3]);
};

int Base64::Encode(string &s)
{
	string s_processed;
	char str_to_operate[3] = { 0 };
	for (size_t i = 0; s.size() >= 3; ++i)
	{
		for (size_t j = 0; j != 3; ++j)
			str_to_operate[j] = s[j];
		s = s.substr(3);
		s_processed += EncodeEach(str_to_operate);
	}
	switch (s.size())
	{
	case 0:break;
	case 1:
		str_to_operate[0] = s[0];
		str_to_operate[1] = 0;
		str_to_operate[2] = 0;
		s_processed += EncodeEach(str_to_operate);
		break;
	case 2:
		str_to_operate[0] = s[0];
		str_to_operate[1] = s[1];
		str_to_operate[2] = 0;
		s_processed += EncodeEach(str_to_operate);
		break;
	}
	s = s_processed;
	return 0;
}

string Base64::EncodeEach(char s[3])
{
	string tmp;
    int index;
	tmp.clear();
	if (s[0] != 0)
	{
		index = s[0] >> 2;
        tmp += Base64EncodeMap[index];
		if (s[1] != 0)
		{
			index = ((s[0] & 0x03) << 4) | (s[1] >> 4);
            tmp += Base64EncodeMap[index];
			if (s[2] != 0)
			{
				index = ((s[1] & 0x0F) << 2) | (s[2] >> 6);
                tmp += Base64EncodeMap[index];
                index = s[2] & 0x3F;
				tmp += Base64EncodeMap[index];
			}
			else
			{
				index = ((s[1] & 0x0F) << 2) | (s[2] >> 6);
                tmp += Base64EncodeMap[index];
				tmp += "=";
			}
		}
		else
		{
			index = ((s[0] & 0x03) << 4) | (s[1] >> 4);
            tmp += Base64EncodeMap[index];
			tmp += "==";
		}
	}
	return tmp;
}


int Base64::EncodeWeb(string &s)
{
	Encode(s);
	for (string::size_type i = 0; i != s.size(); ++i)
	{
		if (s[i] == '+')
			s[i] = '-';
		else if (s[i] == '/')
			s[i] = '_';
	}
	return 0;
}

int Base64::Decode(string &s)
{
	string s_processed;
	char str_to_operate[4];
	for (size_t i = 0; s.size() >= 4; ++i)
	{
		for (size_t j = 0; j != 4; ++j)
		{
			str_to_operate[j] = Base64DecodeMap[s[j]];
		}
		s = s.substr(4);
		s_processed += (str_to_operate[0] << 2) | (str_to_operate[1] >> 4);
		s_processed += (str_to_operate[1] << 4) | (str_to_operate[2] >> 2);
		s_processed += (str_to_operate[2] << 6) | str_to_operate[3];
	}
	s = s_processed;
	return 0;
}

int Base64::DecodeWeb(string &s)
{
	if (s.size() % 4 == 0)
	{
		for (string::size_type i = 0; i != s.size(); ++i)
		{
			if (s[i] == '-')
				s[i] = '+';
			else if (s[i] == '_')
				s[i] = '/';
		}
		Decode(s);
		return 0;
	}
	else return -1;
}

// 依据空格拆分字符串
vector<string> Base64::Split(string aimString)
{
	vector<string> hexNumber;
	string temp;
	for(int i = 0 ; i < aimString.size() ; ++i)
	{
		
		if(aimString.at(i) == ' ')
		{
			hexNumber.push_back(temp);
			temp = "";
			continue;
		}
		stringstream ss;
		ss << aimString.at(i);
		temp += ss.str();
	}

	return hexNumber;
}

int main()
{

	string inputFilePath;
	string outputFilePath;

    ifstream in;
	ofstream out;

	Base64 En;
	Base64 De;
	vector<string> hexDecode;


	cin >> inputFilePath;
	cin >> outputFilePath;

	in.open(inputFilePath);
	out.open(outputFilePath , ios::app);

	// 将hex特征转换为Base64编码
	while(!in.eof())
	{
		string temp;
		getline(in , temp);
		En.EncodeWeb(temp);
		out << temp;
		out << " ";
	}

	in.close();
	out.close();

	in.open(outputFilePath);

	// 解码
	vector<string>().swap(hexDecode);
	while(!in.eof())
	{
		string temp;
		getline(in , temp);
		// 由于转换为Base64编码以后为了区分不同
		hexDecode = De.Split(temp);
		for(vector<string>::iterator it = hexDecode.begin() ; it != hexDecode.end() ; ++it)
		{
			De.Decode(*it);
			cout << *it << endl;
		}
	}
	
    return 0;
}


代码解析

          \;\;\;\;\, 具体编解码思路不做赘述,请参考这位大佬的文章,但是这个大佬的代码有一定缺陷,我在这里进行一下补充,问题在于这个位置

int Base64::Encode(string &s)
{
	char str_to_operate[3] = { 0 };
	for (size_t i = 0; s.size() >= 3; ++i)
	{
		for (size_t j = 0; j != 3; ++j)
			str_to_operate[j] = s[j];
		s = s.substr(3);
		s_processed += EncodeEach(str_to_operate);
	}
	switch (s.size())
	{
	case 0:break;
	case 1:
		str_to_operate[0] = s[0];
		str_to_operate[1] = 0;
		str_to_operate[2] = 0;
		break;
	case 2:
		str_to_operate[0] = s[0];
		str_to_operate[1] = s[1];
		str_to_operate[2] = 0;
		break;
	}
	s_processed += EncodeEach(str_to_operate);
	s = s_processed;
	return 0;
}

          \;\;\;\;\, 上面是那位博主的代码,问题在于跳出switch以后的操作
即:

s_processed += EncodeEach(str_to_operate)

          \;\;\;\;\, 这行代码本身没有问题,问题在于它的位置,这个代码代表了,如果s.size() == 0,即剩余空串时,仍然会用最后三个字符进行一次编码,会导致三个字符重复加密,本人的解决方案就是将这行代码放到case 1和case 2中,这样的话就解决了结尾重复的问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 编码 Base64是一种用64个字符来表示任意二进制数据的编码方式。编码过程就是将二进制数据转换为可打印的ASCII字符集中的字符。 编码的过程如下: - 将传入的数据按照每3个字节一组进行划分。 - 对于每一组,将其转换为4个6位的数字,即24位。 - 将这4个数字转换为4个ASCII字符,即每个字符6位,不足6位的在后面补0。 - 如果原数据的长度不是3的倍数,则在末尾补0,然后用“=”字符表示补了几个0。 C语言中可以使用标准库中的函数实现Base64编码,具体实现如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> const char *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) { *output_length = 4 * ((input_length + 2) / 3); char *encoded_data = malloc(*output_length + 1); if (encoded_data == NULL) return NULL; for (size_t i = 0, j = 0; i < input_length;) { uint32_t octet_a = i < input_length ? data[i++] : 0; uint32_t octet_b = i < input_length ? data[i++] : 0; uint32_t octet_c = i < input_length ? data[i++] : 0; uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; encoded_data[j++] = base64_table[(triple >> 3 * 6) & 0x3F]; encoded_data[j++] = base64_table[(triple >> 2 * 6) & 0x3F]; encoded_data[j++] = base64_table[(triple >> 1 * 6) & 0x3F]; encoded_data[j++] = base64_table[(triple >> 0 * 6) & 0x3F]; } for (size_t i = 0; i < (*output_length % 4); i++) encoded_data[*output_length - 1 - i] = '='; encoded_data[*output_length] = '\0'; return encoded_data; } 2. 解码 Base64解码过程就是将Base64编码的字符串转换为二进制数据。 解码的过程如下: - 将传入的字符串中的“=”字符去掉,将字符串长度调整为4的整数倍。 - 对于每4个字符,将其转换为3个6位的数字,即18位。 - 将这3个数字转换为3个字节的二进制数据。 - 如果编码的数据末尾有1或2个“=”字符,则表示解码后的数据末尾有1或2个字节为0。 C语言中可以使用标准库中的函数实现Base64解码,具体实现如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> const char *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int base64_decode_char(char c) { if (isupper(c)) return c - 'A'; if (islower(c)) return c - 'a' + 26; if (isdigit(c)) return c - '0' + 52; if (c == '+') return 62; if (c == '/') return 63; return -1; } unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) { if (input_length % 4 != 0) return NULL; *output_length = input_length / 4 * 3; if (data[input_length - 1] == '=') (*output_length)--; if (data[input_length - 2] == '=') (*output_length)--; unsigned char *decoded_data = malloc(*output_length); if (decoded_data == NULL) return NULL; for (size_t i = 0, j = 0; i < input_length;) { uint32_t sextet_a = base64_decode_char(data[i++]); uint32_t sextet_b = base64_decode_char(data[i++]); uint32_t sextet_c = base64_decode_char(data[i++]); uint32_t sextet_d = base64_decode_char(data[i++]); uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; } return decoded_data; } 以上就是Base64编码解码的C语言实现。使用时只需要调用相应的函数即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值