Base64编码源码及编码长度计算公式分享(C++)

Base64简介

它实际上是一种“二进制到文本”的编码方法,它能够将给定的任意二进制数据(纯文本当然更没问题)映射为64个ASCII字符组成的字符串的形式,以便在只支持文本的环境中也能够顺利地传输二进制数据。
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),数据不足3字节,用0补足;
因为6位二进制数可以表示64个不同的数,因此只要确定了字符集(含64个字符),并为其中的每个字符确定一个唯一的编码,就可以通过正向与反向映射将二进制字节转换为Base64编码或反之。

编码后的长度如何确定呢

为了保存结果,更合理的分配大小存储,有时候需要确定编码输出后的长度。
从原理来看,转换后的字符串理论上将要比原来的长大约1/3。
更精确的计算公式:(两种情况)

nsrcSize 整型表示原数据的字节数,nrsltSize 整型表示编码后的长度,字节数

  1. 如果不加换行符,一般情况:
	int nrsltSize = ceil(nsrcSize/3.0)*4;  //不足3字节需要补全。使用math.h的ceil(),除数要为小数
	int nrsltSize = (nsrcSize + 2)/3*4;    //更巧妙。充分利用整数相除截断,给予偏移
  1. 如果按照RFC 822规定,输出编码每76个字符,加上一个换行符\n:
	int nrsltSize = (nsrcSize + 2)/3*4 + (nsrcSize-1)/57;   //输出76字符对应原串57字符,58字符就要长度加1

分享下C++实现源码

size_t base64_encode(const char *bytes_to_encode,
    size_t bytes_len, char *encode_bytes, size_t buf_len /* = 0 */)
{
    static const unsigned char s_BASE64[]
        = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    size_t i=0; // 待编码字符索引
    size_t j=0; // 已编码字符索引
    // 输入参数错误,返回0
    if (0 == bytes_to_encode
        || bytes_len < 1
        || 0 == encode_bytes
        || (buf_len != 0 
             && ((bytes_len+2)/3*4 + (bytes_len+56)/57) > buf_len))
    {
        return 0;
    }
    // 编码,按3位一组,不足一组后续特殊处理
    for (i=0, j=0; i+2<bytes_len; i += 3)
    {
        // 编码,按3位一组,转成4位一组
        encode_bytes[j++] = s_BASE64[(bytes_to_encode[i] & 0xfc) >> 2];
        encode_bytes[j++] = s_BASE64[((bytes_to_encode[i] & 0x03) << 4)
            + ((bytes_to_encode[i+1] & 0xf0) >> 4)];
        encode_bytes[j++] = s_BASE64[((bytes_to_encode[i+1] & 0x0f) << 2)
            + ((bytes_to_encode[i+2] & 0xc0) >> 6)];
        encode_bytes[j++] = s_BASE64[bytes_to_encode[i+2] & 0x3f];

        // 每76个字符,增加一个换行符(是否加换行符并不影响编码解码,视情况开启,注意对编码后长度的影响)
        // if (i+3 < bytes_len && 0 == (j+1)%77)
        // {
        //     encode_bytes[j++] = '\n';
        // }
    }
    // 剩余数据,1或2位
    if (i != bytes_len)
    {
        // 编码第1位,正常编码
        encode_bytes[j++] = s_BASE64[(bytes_to_encode[i] & 0xfc) >> 2];
        // 编码第2、3位,根据剩余数据不同,编码方式不同
        if (i+1 == bytes_len)   // 剩余1位数据
        {
            encode_bytes[j++] = s_BASE64[((bytes_to_encode[i] & 0x03) << 4)];
            encode_bytes[j++] = '=';    // 第3位补等号
        }
        else                    // 剩余2位数据
        {
            encode_bytes[j++] = s_BASE64[((bytes_to_encode[i] & 0x03) << 4)
                + ((bytes_to_encode[i+1] & 0xf0) >> 4)];
            encode_bytes[j++] = s_BASE64[((bytes_to_encode[i+1] & 0x0f) << 2)];
        }
        // 第4位,需要补等号
        encode_bytes[j++] = '=';
    }
    // 返回编码后的数据长度
    return j;
}

拿几十M的文件测试了下,计算速度还是蛮快的,1s左右。


myAvatar

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值