Hex, base64 encoding

suggest change

Sometimes 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==

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents