最近项目中遇到 Base64 编码问题,花了点时间总结了一下。
什么是Base64编码?
base64 是网络上最常见的用于传输8bit字节代码的编码方式之一,是一种基于64个可见字符来表示二进制数据的方法。通过3个8bit字节( 3 x 8 = 24 )编码成4个6位字节(4 x 6 = 24),在在每个6位字节前补两个0,形成4个8字节形式。
为什么要有Base64编码?
有些网络上传输渠道并不支持所有字节,比如邮件,ASCII 控制字符 、中文、图片二进制数据等。最好的方法是在不改变传统协议的情况下,开辟一种新方案来支持二进制文件的传输。把不可见字符用可见字符表示。base64就是一种把不可见字符变成可见字符的编码方式。
编码原理?
基本原理
base64 将 ASCII 码 或者二进制编码成只包含 A~Z、a~z、0~9、+ 、/ 这64个字符(26个大写字符、26个小写字符、10个数字、+/)。这64个字符用6bit可以全部表示出来,剩下两个bit高位补零。
编码规则
3个8位字节一组,转换为4个6位字节,再在每个6位字节前面补两个0,构成4位8字节。
base64将3字节转换为4字节,因此编码后的数据长度(以字节为单位),比编码前约多了1/3。如果编码前数据长度刚好是3的倍数,那么恰好多了1/3;如果不是,数据长度除以3的余数就是2或者1,转换的时候结果不足6位的,用0来填充,之后在6位前面补两个0,转换完空出的结果用 = 来补位,最后保证编码出来的字节为4的倍数。
这里需要注意编码后的数据长度:
- 编码前为3的倍数:len = strlen(str_in)/3 * 4
- 编码前不是3的倍数:len = (strlen(str_in)/3 + 1 )* 4
编码范围
- 000000~111111:0~63
- base64 编码表
码值 | 字符 | 码值 | 字符 | 码值 | 字符 | 码值 | 字符 |
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
编码转换
- 3字节字符,刚好 ABC -> QUJD
- 2字节字符,补一个 =(余数为1) AB -> QUI=
- 1字节字符,补两个 = (余数为2) A -> QQ==
Base64开源库介绍
- base64_encode
void base64_encode ( const char *src /* 编码前数据 */ , size_t srclen /* 编码前数据长度 */ , char *out /* 编码后数据 ,输出bufer 至少为输入的4/3 */ , size_t *outlen /* 编码后数据长度 */ , int flags /* 默认为0 */ ) ;
- base64_decode
int base64_decode ( const char *src /* 要解码的数据 */ , size_t srclen /* 要解码的数据长度 */ , char *out /* 解码后数据 ,输出bufer 至少为输入的4/3 */ , size_t *outlen /* 解码后数据长度*/ , int flags /* 默认为0*/ ) ;
- 其他接口见项目源地址。
- 注意在使用的时候需要注意编码前数据buffer的申请,如果出现编码后=后面出现多余字符。第一确保内存空间开辟正确,第二及时清理堆上脏数据。
- 使用base64开源库,可以快速移植到不同的嵌入式平台上,同时还支持simd加速