hex和base32和base64的区别与联系


原文链接: hex和base32和base64的区别与联系

ASCII 是用128(2的8次方)个字符,对二进制数据进行编码的方式

base64编码是用64(2的6次方)个字符,对二进制数据进行编码的方式

base32就是用32(2的5次方)个字符,对二进制数据进行编码的方式

base16就是用16(2的4次方)个字符,对二进制数据进行编码的方式

基本概念

hex也称为base16,意思是使用16个可见字符来表示一个二进制数组,编码后数据大小将翻倍,因为1个字符需要用2个可见字符来表示。

base32,意思是使用32个可见字符来表示一个二进制数组,编码后数据大小变成原来的8/5,也即5个字符用8个可见字符表示,但是最后如果不足8个字符,将用=来补充。

base64,意思是使用64个可见字符来表示一个二进制数组,编码后数据大小变成原来的4/3,也即3个字符用4个可见字符来表示。

package main

import "fmt"
import "encoding/hex"
import "encoding/base32"
import "encoding/base64"

func main() {
	sb := []byte("hello world!")
	hexString := hex.EncodeToString(sb)         // 68656c6c6f20776f726c6421
	hexByte, err := hex.DecodeString(hexString) // [104 101 108 108 111 32 119 111 114 108 100 33] <nil>
	fmt.Println(hexString)
	fmt.Println(hexByte, err)

	base32StdString := base32.StdEncoding.EncodeToString(sb) // NBSWY3DPEB3W64TMMQQQ====
	base32HexString := base32.HexEncoding.EncodeToString(sb) // D1IMOR3F41RMUSJCCGGG====
	base32StdByte, err1 := base32.StdEncoding.DecodeString(base32StdString) // [104 101 108 108 111 32 119 111 114 108 100 33] <nil>
	base32HexByte, err2 := base32.HexEncoding.DecodeString(base32HexString) // [104 101 108 108 111 32 119 111 114 108 100 33] <nil>

	fmt.Println(base32StdString)
	fmt.Println(base32HexString)
	fmt.Println(base32StdByte, err1)
	fmt.Println(base32HexByte, err2)

	base64StdString := base64.StdEncoding.EncodeToString(sb) // aGVsbG8gd29ybGQh
	base64UrlString := base64.URLEncoding.EncodeToString(sb) // aGVsbG8gd29ybGQh
	base64StdByte, err1 := base64.StdEncoding.DecodeString(base64StdString) // [104 101 108 108 111 32 119 111 114 108 100 33] <nil>
	base64UrlByte, err2 := base64.URLEncoding.DecodeString(base64UrlString) // [104 101 108 108 111 32 119 111 114 108 100 33] <nil>

	fmt.Println(base64StdString)
	fmt.Println(base64UrlString)
	fmt.Println(base64StdByte, err1)
	fmt.Println(base64UrlByte, err2)
}

使用场景
有些小伙伴可能有疑问,为啥要把 "hello world!" 这么明白的东西变成一串看不懂的东西,其实是这个例子使用了可见字符而已,而有很多字符是不可见的,我们需要把这些不可见字符变成可见字符。那为啥要变成可见字符?你是看着乱码舒服还是看着可见字符舒服呢?其实不仅仅舒不舒服的问题,有些时候还必须要用可见字符,例如在网络中传输数据时,不同路由器对于不可见字符的处理是不同的,因此可能出现数据错误,因此还必须使用可见字符。

区别与联系
区别主要就是空间效率的区别,base64是具有比较高的空间效率的。当然,hex编码不区分大小写,但是base32与base64是区分的。

联系就是大家都是一种稳定的把二进制数组变成可见字符的编码方式。

base32中StdEncoding和HexEncoding所使用的字符不同,
HexEncoding 是 RFC 4648 中定义的“扩展的十六进制字母”。它通常用于 DNS。
var HexEncoding = NewEncoding(encodeHex)
StdEncoding 是 RFC 4648 中定义的标准 base32 编码。
var StdEncoding = NewEncoding(encodeStd)

base64中URLEncoding一般用于编码URL

本文来自:Segmentfault
hex和base32和base64的区别与联系 - golang - SegmentFault 思否

package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
)

// 实现了base64编码
func main() {


	// 声明内容
	var origin = []byte("Hello World!")
	// 声明buffer
	var buf bytes.Buffer
	// 自定一个64字节的字符串
	var customEncode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
	// 使用给出的字符集生成一个*base64.Encoding,字符集必须是32字节的字符串
	e := base64.NewEncoding(customEncode)
	// 创建一个新的base64流编码器
	w := base64.NewEncoder(e, &buf)
	// 写入
	if _, err := w.Write(origin); err != nil {
		log.Fatal(err)
	}
	// 关闭
	if err := w.Close(); err != nil {
		log.Fatal(err)
	}
	fmt.Println("base64编码内容: ", string(buf.Bytes()))

	// 创建一个新的base64流解码器
	r := base64.NewDecoder(base64.StdEncoding, &buf)
	// 读取内容
	b, err := ioutil.ReadAll(r)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("base64解码内容: ", string(b))



	// 使用标准的base64编码字符集编码
	originEncode := base64.StdEncoding.EncodeToString(origin)
	fmt.Println("base64编码内容: ", originEncode)

	// 使用标准的base64编码字符集解码
	originBytes, err := base64.StdEncoding.DecodeString(originEncode)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("base64解码内容: ", string(originBytes))



	// 获取数据进行base64编码后的最大长度
	var ne = base64.StdEncoding.EncodedLen(len(origin))
	// 声明[]byte
	var dst = make([]byte, ne)
	// 将src的数据编码后存入dst,最多写EncodedLen(len(src))字节数据到dst,并返回写入的字节数
	base64.StdEncoding.Encode(dst, origin)
	fmt.Println("base64编码内容: ", string(dst))

	// 获取base64编码的数据解码后的最大长度
	var nd = base64.StdEncoding.DecodedLen(len(dst))
	// 声明[]byte
	var originText = make([]byte, nd)
	if _, err := base64.StdEncoding.Decode(originText, dst); err != nil {
		log.Fatal(err)
	}
	fmt.Println("base64解码内容: ", string(originText))

	// 创建与enc相同的新编码,指定的填充字符除外,或者nopadding禁用填充。填充字符不能是'\r'或'\n',不能包含在编码的字母表中,并且必须是等于或小于'\xff'的rune
	base64.StdEncoding.WithPadding(base64.StdPadding)
	// base64.StdEncoding 定义标准base64编码字符集
	// base64.URLEncoding 定义用于URL和文件名的,base64编码字符集
	// base64.RawStdEncoding 定义标准无填充字符的base64编码字符集
	// base64.RawURLEncoding 定义用于URL和文件名的,无填充字符的base64编码字符集
}
`