Archve/zip, compress/zlib, compress/gzip packages for Go language learning (the way to go)

Keywords: zlib Unix Linux

Life goes on, go on!!!

Once, I wrote this blog and introduced the use of archive/zip:
The Way to Go

zip zlib gzip

zlib is a data compression library designed to handle simple data regardless of the source.

Gzip is a file compression tool (or a compressed file format generated by the compression tool), which is designed to handle individual files. Gzip uses zlib when compressing data in files. In order to save information related to file attributes, gzip needs to save more header information content in the compressed file (.gz), which zlib does not consider. But gzip only applies to a single file, so the suffixes of compressed packages that we often see on UNIX/Linux are. tar.gz or *.tgz, which is the result of packaging multiple files into a single file with tar first and then compressing them with gzip.

Zip is a format suitable for compressing multiple files (the corresponding tools are PkZip and WinZip, etc.). Therefore, zip files need to contain more information about the file directory structure than gzip headers. However, it should be noted that ZIP format can use a variety of compression algorithms. Most of our common zip files are not compressed by zlib algorithm, and the format of compressed data is quite different from gzip.

archive/zip

Package zip provides support for reading and writing ZIP archives.
Read zip

func unzip_with_archive_zip(archive, target string) error {
    reader, err := zip.OpenReader(archive)
    if err != nil {
        return err
    }

    if err := os.MkdirAll(target, 0755); err != nil {
        return err
    }

    for _, file := range reader.File {
        path := filepath.Join(target, file.Name)
        if file.FileInfo().IsDir() {
            os.MkdirAll(path, file.Mode())
            continue
        }

        fileReader, err := file.Open()
        if err != nil {
            return err
        }
        defer fileReader.Close()

        targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
        if err != nil {
            return err
        }
        defer targetFile.Close()

        if _, err := io.Copy(targetFile, fileReader); err != nil {
            return err
        }
    }

    return nil
}

func zipit_with_archive_zip(source, target string) error {
    zipfile, err := os.Create(target)
    if err != nil {
        return err
    }
    defer zipfile.Close()

    archive := zip.NewWriter(zipfile)
    defer archive.Close()

    info, err := os.Stat(source)
    if err != nil {
        return nil
    }

    var baseDir string
    if info.IsDir() {
        baseDir = filepath.Base(source)
    }

    filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        header, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }

        if baseDir != "" {
            header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
        }

        if info.IsDir() {
            header.Name += "/"
        } else {
            header.Method = zip.Deflate
        }

        writer, err := archive.CreateHeader(header)
        if err != nil {
            return err
        }

        if info.IsDir() {
            return nil
        }

        file, err := os.Open(path)
        if err != nil {
            return err
        }
        defer file.Close()
        _, err = io.Copy(writer, file)
        return err
    })

    return err
}

compress/zlib

Package zlib implements reading and writing of zlib format compressed data, as specified in RFC 1950.
So what is RFC 1950?
A standard specification.

func NewReader

func NewReader(r io.Reader) (io.ReadCloser, error)

NewReader creates a new ReadCloser.

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter creates a new Writer. Writes to the returned Writer are compressed and written to w.

func zipit_with_compress_zlib() {
    var b bytes.Buffer

    w := zlib.NewWriter(&b)
    w.Write([]byte("hello, world\n"))
    w.Close()
    fmt.Println(b.Bytes())
    // Output: [120 156 202 72 205 201 201 215 81 40 207 47 202 73 225 2 4 0 0 255 255 33 231 4 147]
}

func unzip_with_compress_zlib() {
    buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
        47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
    b := bytes.NewReader(buff)

    r, err := zlib.NewReader(b)
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, r)
    r.Close()
}

compress/gzip

Package gzip implements reading and writing of gzip format compressed files, as specified in RFC 1952.
Here you can clearly see the difference between gzip and zlib packages: compressed files in different formats.

func NewReader

func NewReader(r io.Reader) (*Reader, error)

NewReader creates a new Reader reading the given reader. If r does not also implement io.ByteReader, the decompressor may read more data than necessary from r.

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter returns a new Writer. Writes to the returned writer are compressed and written to w.

Example:

package main

import (
    "compress/gzip"
    "fmt"
    "os"
)

func main() {

    original := "Hello World!"
    f, _ := os.Create("./file.gz")
    w := gzip.NewWriter(f)
    w.Write([]byte(original))
    w.Close()
    fmt.Println("COMPRESS DONE")

    f, _ = os.Open("./file.gz")
    reader, _ := gzip.NewReader(f)
    result := make([]byte, 100)
    count, _ := reader.Read(result)
    fmt.Println(count)
    fmt.Println(string(result))
}

func NewWriterLevel

func NewWriterLevel(w io.Writer, level int) (*Writer, error)

NewWriterLevel is like NewWriter but specifies the compression level instead of assuming DefaultCompression.

Constant:

const (
        NoCompression      = flate.NoCompression
        BestSpeed          = flate.BestSpeed
        BestCompression    = flate.BestCompression
        DefaultCompression = flate.DefaultCompression
        HuffmanOnly        = flate.HuffmanOnly
)

Example:

package main

import (
    "compress/gzip"
    "fmt"
    "os"
)

func main() {
    test := "There are moments in life when you miss someone so much that you just want to pick them from your dreams and hug them for real!"
    test += "Dream what you want to dream;"
    test += "go where you want to go;"
    test += "be what you want to be,because you have only one life and one chance to do all the things you want to do."

    // Write with BestSpeed.
    fmt.Println("BESTSPEED")
    f, _ := os.Create("./file-bestspeed.gz")
    w, _ := gzip.NewWriterLevel(f, gzip.BestSpeed)
    w.Write([]byte(test))
    w.Close()

    // Write with BestCompression.
    fmt.Println("BESTCOMPRESSION")
    f, _ = os.Create("./file-bestcompression.gz")
    w, _ = gzip.NewWriterLevel(f, gzip.BestCompression)
    w.Write([]byte(test))
    w.Close()
}

Posted by jwilley on Wed, 26 Dec 2018 15:54:07 -0800