30.Go Hex和 base64编码

有时候你需要将bytes编码非文本text.

最流行的编码是十六进制,其中每个字节由2个字符表示,而base64则将每个3个字节编码为4个字符。

Hex编码和解码

我们可以把[]byte编码为string,也可以把string解码为 []byte

d := []byte{0x01, 0xff, 0x3a, 0xcd}
s := hex.EncodeToString(d)
fmt.Printf("Hex: %s\n", s)

d2, err := hex.DecodeString(s)
if err != nil {
    log.Fatalf("hex.DecodeString() failed with '%s'\n", err)
}
if !bytes.Equal(d, d2) {
    log.Fatalf("decoded version is different than original")
}

Hex: 01ff3acd

使用fmt.Sprintf编码Hex

我们可以使用fmt.Sprintf和%x指令编码为字符串。 同样,我们可以使用fmt.Sscanf和%x进行解码。

指令%x除[] byte外还支持整数。

d := []byte{0x01, 0xff, 0x3a, 0xcd}
s := fmt.Sprintf("%x", d)
fmt.Printf("Hex: %s\n", s)

var decoded []byte
_, err := fmt.Sscanf(s, "%x", &decoded)
if err != nil {
    log.Fatalf("fmt.Sscanf() failed with '%s'\n", err)
}
if !bytes.Equal(d, decoded) {
    log.Fatalf("decoded version is different than original")
}

n := 3824
fmt.Printf("%d in hex is 0x%x\n", n, n)

Hex: 01ff3acd
3824 in hex is 0xef0

十六进制编码到writer,从reader解码

为了在流模式下对较大的值进行编码和解码,我们可以编码为io.Writer并从io.Reader进行解码。

d := []byte{0x01, 0xff, 0x3a, 0xcd}

writer := &bytes.Buffer{}
hexWriter := hex.NewEncoder(writer)

_, err := hexWriter.Write(d)
if err != nil {
    log.Fatalf("hexWriter.Write() failed with '%s'\n", err)
}

encoded := writer.Bytes()
fmt.Printf("Hex: %s\n", string(encoded))

reader := bytes.NewBuffer(encoded)
hexReader := hex.NewDecoder(reader)

decoded, err := ioutil.ReadAll(hexReader)
if err != nil {
    fmt.Printf("ioutil.ReadAll() failed with '%s'\n", err)
}

if !bytes.Equal(d, decoded) {
    log.Fatalf("decoded version is different than original")
}

Hex: 01ff3acd

Base64编码和解码

使用base64也可以编码[]byte

d := []byte{0x01, 0xff, 0x3a, 0xcd}
s := base64.StdEncoding.EncodeToString(d)
fmt.Printf("base64: %s\n", s)

d2, err := base64.StdEncoding.DecodeString(s)
if err != nil {
    log.Fatalf("hex.DecodeString() failed with '%s'\n", err)
}
if !bytes.Equal(d, d2) {
    log.Fatalf("decoded version is different than original")
}

base64: Af86zQ==

URL-safe base64

不幸的是,原始的base64编码可能会产生在URL中无效的字符。

考虑到网址在当时很重要,因此我们提供了一种base64编码的变体,它没有该缺陷:

d := []byte{0x01, 0xff, 0x3a, 0xcd}
s := base64.URLEncoding.EncodeToString(d)
fmt.Printf("base64: %s\n", s)

d2, err := base64.URLEncoding.DecodeString(s)
if err != nil {
    log.Fatalf("hex.DecodeString() failed with '%s'\n", err)
}
if !bytes.Equal(d, d2) {
    log.Fatalf("decoded version is different than original")
}

base64: Af86zQ==

Base64编码到写入器,从读取器解码

为了在流模式下对较大的值进行编码和解码,我们可以编码为io.Writer并从io.Reader进行解码。

d := []byte{0x01, 0xff, 0x3a, 0xcd}

writer := &bytes.Buffer{}
base64Writer := base64.NewEncoder(base64.StdEncoding, writer)

_, err := base64Writer.Write(d)
if err != nil {
    log.Fatalf("base64Writer.Write() failed with '%s'\n", err)
}
err = base64Writer.Close()
if err != nil {
    log.Fatalf("base64Writer.Close() failed with '%s'\n", err)
}

encoded := writer.Bytes()
fmt.Printf("Base64: %s\n", string(encoded))

reader := bytes.NewBuffer(encoded)
base64Reader := base64.NewDecoder(base64.StdEncoding, reader)

decoded, err := ioutil.ReadAll(base64Reader)
if err != nil {
    fmt.Printf("ioutil.ReadAll() failed with '%s'\n", err)
}

if !bytes.Equal(d, decoded) {
    log.Fatalf("decoded version is different than original")
}

Base64: Af86zQ==

你可能感兴趣的:(30.Go Hex和 base64编码)