base16,base32,base64的意义和原理

105 阅读2分钟
/*
先说下这些编码的作用。我们知道,有的字符在一些环境中是不能显示或使用的,比如 &, = 等字符在 URL 被保留为特殊作用的字符;
比如描述一张图片,而图片中的二进制码如果转成对应的字符的话,会有很多不可见字符和控制符(如换行、回车之类),这时就需要对进行编码。
Base 系列的就是用来将字节编码为 ASCII 中的可见字符的。
*/

//base16编码出来的字节数一定是2的倍数;base32编码出来的字节长度一定是8的倍数;base64编码出来的字节数一定是4的倍数
//疑问:为什么base16不需要切字节,base32需要5个字节切一组,base64需要3个字节切一组?
//【base16每4个bit编一个码,单字节也能完成编码;base32每5个bit编一个码,单个字节8bit,遍了一个以后剩下的3个bit没法处理,所以最小需要5个字节切一组;base64每6个字节遍一个码,3个字节就能完全使用完,所以3个字节切一组】
// 空间占用【base16会翻倍,base32为8/5,base64为4/3】在数据量大的情况下,后面的填充可以忽略不计,空间浪费比为【2>1.6>1.33】
// base16编码遍出来的都是数字和小写字母,看起来比较方便,一般对外暴露的openid都加密后再base16编码放出去
func TestBase16(t *testing.T) {
	// 00000001 00000010 00000011
	b := []byte{1, 2, 3}
	//十六进制编码,每4个bit用一个asic替换,长度扩大一倍【Base16 编码会将bit切为4个一组,所以此编码后会用到2e4=16个字符,数据会扩大二倍】
	//【这十六个字符分别是 0-9A-F】
	fmt.Println("hex:========")
	fmt.Println(hex.EncodeToString(b))
	//Base32 编码会用到2e5=32个字符,数据量扩大了 8/5【Base32 编码会将字节切为5个一组,每5个字节可以重组为 8 个字符。如果不够 5 个字节,那么就在切出的最后一组后边充 0,充够 5 位,然后右边充 =,充够 8组。】
	//【Base32中只有大写字母(A-Z)和数字234567;】
	fmt.Println("base32:===========")
	fmt.Println(base32.StdEncoding.EncodeToString(b))
	//【Base64 编码和 Base32 在同小异。是将每 3 个字节重组为 4 组,每组 6 位,会用到2e6=64个字符。填充 0 和 = 的方法和 Base 32 一样。Base64 编码后,数据量扩大了 4/3。】
	//【包含大写字母(A-Z),小写字母(a-z),数字(0-9)以及+/;】
	fmt.Println("base64:=============")
	fmt.Println(base64.StdEncoding.EncodeToString(b))
}


=== RUN   TestBase16
hex:========
010203
base32:===========
AEBAG===
base64:=============
AQID
--- PASS: TestBase16 (0.00s)
PASS