author
Kevin Kelche

Data Compression with Zlib in Golang


Introduction

Zlib is a lossless data compression library used in many applications. It’s used in web servers, file compression utilities, and other applications where efficient data compression is needed. This library is fast, portable, and easy to use. This article will teach us how to compress and decompress data with Zlib in Go.

Golang has a built-in package called compress/zlib that provides the functionality to compress and decompress data using the Zlib algorithm.

Zlib Compression

The compress/zlib package provides a Writer type used to compress data. The Writer type implements the io.Writer interface. Meaning we can use the Writer type to compress data from any source that implements the io.Writer interface, be it a file, a network connection, or a string.

main.go
package main

import (
 "bytes"
 "compress/zlib"
 "fmt"
 "io"
 "os"
)

func main() {
 var buffer bytes.Buffer

 w := zlib.NewWriter(&buffer)

    w.Write([]byte("Working with Zlib\n"))

    w.Close()
    fmt.Println(buffer.Bytes())

    io.Copy(os.Stdout, &buffer)
}

Copied!

In this example, we create a bytes.Buffer to write our compressed data. We then make a new zlib.Writer and pass in the buffer as the destination. We then write some uncompressed data to the Writer and close it. This flushes the compressed data to the buffer. Finally, we write the compressed data to standard output.

If you check the output of the program, you will see that the compressed data is different from the uncompressed data.

terminal
$ go run main.go
[120 156 10 207 47 202 206 204 75 87 40 207 44 201 80 136 202 201 76 226 2 4 0 0 255 255 65 134 6 121]
x�
�/���KW(�,�P���L���A�y%

Copied!

Zlib Decompression

To decompress data, we use the Reader type provided by the package. The Reader type implements the io.Reader interface. The NewReader function implements the Reader function and takes in an io.Reader as the source of the compressed data.

main.go
package main

import (
 "bytes"
 "compress/zlib"
 "io"
 "os"
)

func main() {
 buffer := bytes.NewBuffer([]byte{120, 156, 10, 207, 47, 202, 206, 204, 75, 87, 40, 207, 44, 201, 80, 136, 202, 201, 76, 226, 2, 4, 0, 0, 255, 255, 65, 134, 6, 121})

 r, err := zlib.NewReader(buffer)
 if err != nil {
 panic(err)
    }

    io.Copy(os.Stdout, r)
}

Copied!

In this example, we create a bytes.Buffer and pass in the compressed data. We then create a new zlib.Reader and pass it into the buffer as the compressed data source. We then write the decompressed data to standard out.

output
$ go run main.go
Working with Zlib

Copied!

Data Compression over the Network

In the previous examples, we compressed and decompressed data from a buffer. In this example, we’ll compress and decompress data sent over the network.

This client-server example simulates that a user sends a message to a server. The client will first compress the message and send it to the server. The server will then decompress the message and print it to standard output.

server.go
package main

import (
 "compress/zlib"
 "fmt"
 "io"
 "net"
 "os"
)

func main() {
 listener, err := net.Listen("tcp", ":8080")
 if err != nil {
 panic(err)
    }

 for {
 conn, err := listener.Accept()
 if err != nil {
 panic(err)
        }

 go handleConnection(conn)
    }
}

func handleConnection(connection net.Conn) {
 r, err := zlib.NewReader(connection)
 if err != nil {
 panic(err)
    }

    io.Copy(os.Stdout, r)
}

Copied!

client.go
package main

import (
 "bufio"
 "compress/zlib"
 "fmt"
 "net"
 "os"
)

func main() {
 connection, err := net.Dial("tcp", "localhost:8080")
 if err != nil {
 panic(err)
    }

 w := zlib.NewWriter(connection)

 defer w.Close()

 for {
        fmt.Print("Enter text: ")
 reader := bufio.NewReader(os.Stdin)
 text, _ := reader.ReadString('\n')

        w.Write([]byte(text))
        w.Flush()
    }

}

Copied!

In the server, we create a new zlib.Reader and pass in the connection as the compressed data source. We then write the decompressed data to standard out. On the client, we create a new zlib.Writer and pass in the connection as the destination. We then write the compressed data to the server. By running the client and server, we can see that the data is sent over the network compressed, and decompressed on the server with no issues.

Conclusion

In this article, we explored how to compress and decompress data with Zlib in Go using the compress/zlib package. Now armed with this knowledge, go forth and explore compressing other data formats like PNG that we never got to cover in this article.

Subscribe to my newsletter

Get the latest posts delivered right to your inbox.