Base64如何编码及长度计算公式
Base64简介
它实际上是一种“二进制到文本”的编码方法,它能够将给定的任意二进制数据(纯文本当然更没问题)映射为64个ASCII字符组成的字符串的形式,以便在只支持文本的环境中也能够顺利地传输二进制数据。
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),数据不足3字节,用0补足;
因为6位二进制数可以表示64个不同的数,因此只要确定了字符集(含64个字符),并为其中的每个字符确定一个唯一的编码,就可以通过正向与反向映射将二进制字节转换为Base64编码或反之。
编码后的长度如何确定呢
为了保存结果,更合理的分配大小存储,有时候需要确定编码输出后的长度。
从原理来看,转换后的字符串理论上将要比原来的长大约1/3。
更精确的计算公式:(两种情况)
nsrcSize 整型表示原数据的字节数,nrsltSize 整型表示编码后的长度,字节数
- 如果不加换行符,一般情况:
int nrsltSize = ceil(nsrcSize/3.0)*4; //不足3字节需要补全。使用math.h的ceil(),除数要为小数
int nrsltSize = (nsrcSize + 2)/3*4; //更巧妙。充分利用整数相除截断,给予偏移
- 如果按照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左右。