Base64编码原理,快速掌握

Base64编码,是我们程序开发中经常使用到的编码方法。它是一种基于用64个可打印字符来表示二进制数据的表示方法。它通常用作存储、传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用作电子邮件标准)中一种可打印字符表示二进制数据的常见编码方法!它其实只是定义用可打印字符传输内容一种方法,并不会产生新的字符集!有时候,我们学习转换的思路后,我们其实也可以结合自己的实际需要,构造一些自己接口定义编码方式。好了,我们一起看看,它的转换思路吧!

Base64实现转换原理

它是用64个可打印字符表示二进制所有数据方法。由于2的6次方等于64,所以可以用每6个位元为一个单元,对应某个可打印字符。我们知道三个字节有24个位元,就可以刚好对应于4个Base64单元,即3个字节需要用4个Base64的可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中一般有所不同。但是,我们经常所说的Base64另外2个字符是:“+/”。这64个字符,所对应表如下。

编号

字符

编号

字符

编号

字符

编号

字符

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

/

转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的bit用0补足。然后,每次取出6个bit,按照其值选择 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。

如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

编码后的数据比原始数据略长,为原来的4/3。无论什么样的字符都会全部被编码,因此不像Quoted-printable 编码,还保留部分可打印字符。所以,它的可读性不如Quoted-printable编码!

文本

M

a

n

ASCII编码

77

97

110

二进制位

0

1

0

0

1

1

0

1

0

1

1

0

0

0

0

1

0

1

1

0

1

1

1

0

索引

19

22

5

46

Base64编码

T

W

F

u

M的Ascii码是77,前六位对应值为19,对应base64字符是T,如此类推。其它字符编码就可以自动转换得到!我们看看另外不是刚好是3个字节的情况!

文本(1 Byte)

A

二进制位

0

1

0

0

0

0

0

1

二进制位(补0)

0

1

0

0

0

0

0

1

0

0

0

0

Base64编码

Q

Q

=

=

文本(2 Byte)

B

C

二进制位

0

1

0

0

0

0

1

0

0

1

0

0

0

0

1

1

x

x

x

x

x

x

二进制位(补0)

0

1

0

0

0

0

1

0

0

1

0

0

0

0

1

1

0

0

x

x

x

x

x

x

Base64编码

Q

k

M

=

Base64转换代码实现

既然知道了方法,那么我们如果要自己写个简单转换,好像也是很容易的!下面,我写下我做转换php代码!

<?php /** *base64编码方法、本方法只是做base64转换过程代码举例说明,通过该例子可以任意改造不同语言版 *@author 程默 *@copyright http://blog.chacuo.net *@param $src 原字符串 *@return string base64字符串* */ function c_base64_encode($src) { static $base="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ////将原始的3个字节转换为4个字节 $slen=strlen($src); $smod = ($slen%3); $snum = floor($slen/3); $desc = array(); for($i=0;$i<$snum;$i++) { ////读取3个字节 $_arr = array_map('ord',str_split(substr($src,$i*3,3))); ///计算每一个base64值 $_dec0= $_arr[0]>>2; $_dec1= (($_arr[0]&3)<<4)|($_arr[1]>>4); $_dec2= (($_arr[1]&0xF)<<2)|($_arr[2]>>6); $_dec3= $_arr[2]&63; $desc =array_merge($desc,array($base[$_dec0],$base[$_dec1],$base[$_dec2],$base[$_dec3])); } if($smod==0) return implode('',$desc); ///计算非3倍数字节 $_arr = array_map('ord',str_split(substr($src,$snum*3,3))); $_dec0= $_arr[0]>>2; ///只有一个字节 if(!isset($_arr[1])) { $_dec1= (($_arr[0]&3)<<4); $_dec2=$_dec3="="; } else { ///2个字节 $_dec1= (($_arr[0]&3)<<4)|($_arr[1]>>4); $_dec2= $base[($_arr[1]&7)<<2]; $_dec3="="; } $desc = array_merge($desc,array($base[$_dec0],$base[$_dec1],$_dec2,$_dec3)); return implode('',$desc); }

好了,通过这个例子,我想base64编码转换原理、算法有些了解了吧!它转换过程很简单,只需要做个映射表,然后将原先做一些移位运算就可以完成!我们通过该例子,是不是可以做个自己的base32这类的编码呢!欢迎朋友们交流!

原文发布于微信公众号 - nginx(nginx-study)

原文发表时间:2016-02-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大数据学习笔记

Java程序设计(Java9版):第2章 数据类型与运算符(Data types and Operators)

第2章 数据类型与运算符(Data types and Operators) I think everybody in this country should ...

28850
来自专栏Java进阶之路

Java8 Optional 的正确使用方式

21300
来自专栏星汉技术

HIVE内置函数

86160
来自专栏blackheart的专栏

[C#1] 8-数组

1.数组概述 声明数组: //每个元素初始化为0,虽然数组元素是值类型,但是却是分配在托管堆中的; int[] myArray=new int[100]; //...

19970
来自专栏PHP在线

开发中遇到一个数据库字段问题

大牛不必浪费时间了,适合初学者。 今天遇到一个问题,数据库字段问题。 有一张表存储着用户消费记录,设计表时使用的是整形,后来增加需求,需要对业务做些改动,改过之...

35160
来自专栏指尖下的Android

Java &、&&、|、||、^、<<、>>、~、>>>等运算符

无符号右移运算符和右移运算符的主要区别在于负数的计算,因为无符号右移是高位补0,移多少位补多少个0。

19K40
来自专栏前端小栈

正则详解

转自: JS正则表达式一条龙讲解,从原理和语法到JS正则、ES6正则扩展,最后再到正则实践思路

15930
来自专栏HansBug's Lab

1798: [Ahoi2009]Seq 维护序列seq

1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 2930...

31350
来自专栏xingoo, 一个梦想做发明家的程序员

20120918-双向链表类定义《数据结构与算法分析》

将新的节点插入双向链表的时候: iterator insert(iterator itr,const Object & x)//向双向链表中插入一个x节点 { ...

23660
来自专栏chenjx85的技术专栏

leetcode-179-Largest Number(理解规则,自定义cmp函数进行排序)

1、这道题给定一个vector,里面存放着int类型的非负整数,要求把这些非负整数拼起来,尽可能拼成一个最大的整数。

20630

扫码关注云+社区

领取腾讯云代金券