Hex, base64 encoding
suggest changeSometimes you need to encode bytes into a text.
Most popular encodings are hex, where each byte is represented by 2 characters and base64 where each 3 bytes are encoded as 4 characters.
Hex encode and decode
We can encode a []byte
into a string
and decode from string
into []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
Hex encoding with fmt.Sprintf
We can encode to string using fmt.Sprintf
and %x
directive. Similarly, we can decode using fmt.Sscanf
and %x
.
Directive %x
supports integers in addtion to []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
Hex encoding to writer, decoding from reader
For encoding and decoding larger values in streaming mode, we can encode to a io.Writer
and decode from 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 encode and decode
We can encode a []byte
into a string
and decode from string
into []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
Original base64 encoding unfortunately might produce characters that are not valid in urls.
Given that urls are important those days we have a variant of base64 encoding that doesn’t have that flaw:
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 encoding to writer, decoding from reader
For encoding and decoding larger values in streaming mode, we can encode to an io.Writer
and decode from 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==