Base64编解码类

Base64的原理:

解析一:就是把3个8位的char,通过位运算,变成4个6位的char。再经过高两位,也就是把256个选择变成了64个选择。而64个刚好是ASCII码中可以用来输出的64个字符,大小写英文字母52个+10个数字+两个特殊字符‘+’和‘/’,。

解析二:Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

总结:用一句话来说明Base64编码的原理:“把3个字节变成4个字节”。

比如某一字符串转成字节码为:

11011001 01101010 00101100

110110010110101000101100

00110110 00010110 00101000 00101100

把8位的字节连成一串110110010110101000101100

然后每次顺序选6个出来之后再把这6二进制数前面再添加两个0,就成了一个新的字节。之后再选出6个来,再添加0,依此类推,直到24个二进制数全部被选完。

当代码量不是3的整数倍时,代码量/3的余数自然就是2或者1。转换的时候,结果不够6位的在后面用0来补上相应的位置,之后再在6位的前面补两个0。转换完空出的结果就用就用“=”来补位。

如果余1,就补“==”

如果余2,就补“=”

#include <iostream>
#include <string>
#include <fstream>


using namespace std;

class Base64
{
public:
    Base64()
    {
        m_code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    };
    //编码为base64
    std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len)
    {
        std::string encode;
        int i = 0;
        int j = 0;
        unsigned char char_array_3[3];
        unsigned char char_array_4[4];

        while (in_len--)
        {
            char_array_3[i++] = *(bytes_to_encode++);
            if(i == 3)
            {
                char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
                char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);//第一个char的后两位加后一个char的高四位
                char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);//第二个char的后四位+第三个char的高两位
                char_array_4[3] = char_array_3[2] & 0x3f;//第三个char的低六位

                for(i = 0; (i <4) ; i++)
                    encode += m_code[char_array_4[i]];
                i = 0;
            }
        }

        if(i)
        {
            for(j = i; j < 3; j++)
                char_array_3[j] = '\0';

            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (j = 0; (j < i + 1); j++)
                encode += m_code[char_array_4[j]];

            while((i++ < 3))
                encode += '=';
        }

        return encode;
    };
    //进行base64解码
    std::string base64_decode(std::string const &encoded_string)
    {
        int in_len = encoded_string.size();
        int i = 0;
        int j = 0;
        int in_ = 0;
        unsigned char char_array_4[4], char_array_3[3];
        std::string decode;

        while(in_len--
                && (encoded_string[in_] != '=')
                && is_base64(encoded_string[in_])
                )
        {
            char_array_4[i++] = encoded_string[in_]; in_++;
            if(i ==4)
            {
                for(i = 0; i <4; i++)
                    char_array_4[i] = m_code.find(char_array_4[i]);

                char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
                char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
                char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

                for(i = 0; (i < 3); i++)
                    decode += char_array_3[i];
                i = 0;
            }
        }

        if(i)
        {
            for(j = i; j <4; j++)
                char_array_4[j] = 0;

            for(j = 0; j <4; j++)
                char_array_4[j] = m_code.find(char_array_4[j]);

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for(j = 0; (j < i - 1); j++)
                decode += char_array_3[j];
        }

        return decode;
    };

private:
    inline bool is_base64(unsigned char c)
    {
        return (isalnum(c) || (c == '+') || (c == '/'));
    };

private:
    std::string m_code;
};


int main()
{
    //Base64 bs64;
    std::fstream f;
    f.open("1.jpg", std::ios::in | std::ios::binary);
    if(!f.is_open())
	{
		cout<<"File open failed."<<endl;
		f.close(); //关闭文件以保存其内容
	}
    f.seekg(0, std::ios_base::end);     //设置偏移量至文件结尾
    std::streampos sp = f.tellg();      //获取文件大小
    int size = sp;
    char* buffer = (char*)malloc(sizeof(char) * size);
    f.seekg(0, std::ios_base::beg);     //设置偏移量至文件开头
    f.read(buffer, size);                //将文件内容读入buffer
    std::string imgBase64 =Base64().base64_encode((unsigned char const *)buffer, size);    
    std::string s_mat = Base64().base64_decode(imgBase64.c_str());
    f.close();

    FILE* stream;
    if ((stream = fopen("2.jpg", "wb")) != NULL)
    {
         //将解码后的数据写入新文件
        int numwritten = fwrite(s_mat.data(), sizeof(char), s_mat.size(), stream);
        fclose(stream);
    } 

    return 0;
}

要考虑到的一点是,编解码有时候不会一次性完成,为什么呢,实际情况中,要编解码的字符串可能很长,你不可能把字符串一次性读到内存中,因此就要分批编解码,但是我们编码是以3个字节为一组进行编码,因此,在类中需要设置一个缓存,长度为3,当缓存满了,就直接让3个字节去编码。

参考:Base64编解码及其C++实现_FlushHip的博客-CSDN博客_base62 c++

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值