zoukankan      html  css  js  c++  java
  • C++实现base64编码

    将昨天的php代码改造成C++

    /*base_64.h文件*/
    #ifndef BASE_64_H
    #define BASE_64_H
    /**
     * Base64 编码/解码
     * @author liruixing
     */
    class Base64{
    private:
        std::string _base64_table;
        static const char base64_pad = '=';public:
        Base64()
        {
            _base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /*这是Base64编码使用的标准字典*/
        }
        /**
         * 这里必须是unsigned类型,否则编码中文的时候出错
         */
        std::string Encode(const unsigned char * str,int bytes);
        std::string Decode(const char *str,int bytes);
        void Debug(bool open = true);
    };
    #endif

    上面定义了一个头文件,定义base64的类

    /*base_64.cpp文件*/
    #include <iostream>
    #include <string>
    #include <cstring>
    #include "base_64.h"
    
    std::string Base64::Encode(const unsigned char * str,int bytes) {
        int num = 0,bin = 0,i;
        std::string _encode_result;
        const unsigned char * current;
        current = str;
        while(bytes > 2) {
            _encode_result += _base64_table[current[0] >> 2];
            _encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
            _encode_result += _base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
            _encode_result += _base64_table[current[2] & 0x3f];
    
            current += 3;
            bytes -= 3;
        }
        if(bytes > 0)
        {
            _encode_result += _base64_table[current[0] >> 2];
            if(bytes%3 == 1) {
                _encode_result += _base64_table[(current[0] & 0x03) << 4];
                _encode_result += "==";
            } else if(bytes%3 == 2) {
                _encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
                _encode_result += _base64_table[(current[1] & 0x0f) << 2];
                _encode_result += "=";
            }
        }
        return _encode_result;
    }
    std::string Base64::Decode(const char *str,int length) {
           //解码表
        const char DecodeTable[] =
        {
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -2, -1, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
            -2,  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, -2, -2, -2, -2, -2,
            -2, 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, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
            -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
        };
        int bin = 0,i=0,pos=0;
        std::string _decode_result;
        const char *current = str;
        char ch;
        while( (ch = *current++) != '' && length-- > 0 )
        {
            if (ch == base64_pad) { // 当前一个字符是“=”号
                /*
                先说明一个概念:在解码时,4个字符为一组进行一轮字符匹配。
                两个条件:
                    1、如果某一轮匹配的第二个是“=”且第三个字符不是“=”,说明这个带解析字符串不合法,直接返回空
                    2、如果当前“=”不是第二个字符,且后面的字符只包含空白符,则说明这个这个条件合法,可以继续。
                */
                if (*current != '=' && (i % 4) == 1) {
                    return NULL;
                }
                continue;
            }
            ch = DecodeTable[ch];
            //这个很重要,用来过滤所有不合法的字符
            if (ch < 0 ) { /* a space or some other separator character, we simply skip over */
                continue;
            }
            switch(i % 4)
            {
                case 0:
                    bin = ch << 2;
                    break;
                case 1:
                    bin |= ch >> 4;
                    _decode_result += bin;
                    bin = ( ch & 0x0f ) << 4;
                    break;
                case 2:
                    bin |= ch >> 2;
                    _decode_result += bin;
                    bin = ( ch & 0x03 ) << 6;
                    break;
                case 3:
                    bin |= ch;
                    _decode_result += bin;
                    break;
            }
            i++;
        }
        return _decode_result;
    }

    base64类中方法的定义实际上是在base_64.cpp中进行的。

    上面的两个文件用来生成一个静态链接库:libbase_64.a

    g++ -c base_64.cpp
    ar rs libbase_64.a base_64.o

    下面来进行实际的测试:

    /*main.cppe文件*/
    #include <iostream>
    #include "base_64.h"
    
    using namespace std;
    int main()
    {
        unsigned char str[] = "这是一条测试数据:http://img.v.cmcm.com/7dd6e6d7-0c2d-5a58-a072-71f828b94cbc_crop_216x150.jpg";
        string normal,encoded;
        int i,len = sizeof(str)-1;
        Base64 *base = new Base64();
        encoded = base->Encode(str,len);
        cout << "base64 encode : " << encoded << endl;
        len = encoded.length();
        const char * str2 = encoded.c_str();
        normal = base->Decode(str2,len);
        cout << "base64 decode : " << normal <<endl;
        return 0;
    }

    编译代码并运行

    g++ main.cpp -L. -lbase_64 -Ibase_64 -o main
    ./main

    正常数据的encode和decode输出效果:

    包含异常数据的decode输出效果:

    在改造昨天的php代码过程中,还参考php源码base64.c中相关逻辑的实现。

  • 相关阅读:
    周强 201771010141 《面向对象程序设计(Java)》第十一周学习总结
    周强 201771010141《面对对象程序设计(java)》第十周学习总结
    周强 201771010141 《面向对象程序设计(java)》第九周实验总结
    周强201771010141《面向对象程序设计(java)》第六周学习总结
    周强201771010141《面向对象程序设计Java》第八周学习总结
    周强 201771010141 《面向对象程序设计(java)》第七周学习总结
    周强 201771010141《面向对象程序设计(java)》第四周学习总结
    «面向对象程序设计(java)»第三周学习总结 周强 201771010141
    周强 201771010141 《面向对象程序设计(java)》 第二周学习总结
    201771010109 焦旭超《面向对象程序设计(java)》第十二周学习总结
  • 原文地址:https://www.cnblogs.com/lrxing/p/5535601.html
Copyright © 2011-2022 走看看