最近项目中遇到 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 

一文搞懂Base64编解码_数据



2字节字符,补一个 =(余数为1) AB -> QUI= 

一文搞懂Base64编解码_编码方式_02



1字节字符,补两个 = (余数为2) A -> QQ==

一文搞懂Base64编解码_数据_03



Base64开源库介绍


  • 项目地址:https://github.com/aklomp/base64.git
  • 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加速