How can I use the “compress/gzip” package to gzip a file?

前端 未结 5 1236
长情又很酷
长情又很酷 2020-12-13 18:48

I\'m new to Go, and can\'t figure out how to use the compress/gzip package to my advantage. Basically, I just want to write something to a file, gzip it and rea

相关标签:
5条回答
  • 2020-12-13 18:57

    I decided to combine ideas from others answers and just provide a full example program. Obviously there are many different ways to do the same thing. This is just one way:

    package main
    
    import (
        "compress/gzip"
        "fmt"
        "io/ioutil"
        "os"
    )
    
    var zipFile = "zipfile.gz"
    
    func main() {
        writeZip()
        readZip()
    }
    
    func writeZip() {
        handle, err := openFile(zipFile)
        if err != nil {
            fmt.Println("[ERROR] Opening file:", err)
        }
    
        zipWriter, err := gzip.NewWriterLevel(handle, 9)
        if err != nil {
            fmt.Println("[ERROR] New gzip writer:", err)
        }
        numberOfBytesWritten, err := zipWriter.Write([]byte("Hello, World!\n"))
        if err != nil {
            fmt.Println("[ERROR] Writing:", err)
        }
        err = zipWriter.Close()
        if err != nil {
            fmt.Println("[ERROR] Closing zip writer:", err)
        }
        fmt.Println("[INFO] Number of bytes written:", numberOfBytesWritten)
    
        closeFile(handle)
    }
    
    func readZip() {
        handle, err := openFile(zipFile)
        if err != nil {
            fmt.Println("[ERROR] Opening file:", err)
        }
    
        zipReader, err := gzip.NewReader(handle)
        if err != nil {
            fmt.Println("[ERROR] New gzip reader:", err)
        }
        defer zipReader.Close()
    
        fileContents, err := ioutil.ReadAll(zipReader)
        if err != nil {
            fmt.Println("[ERROR] ReadAll:", err)
        }
    
        fmt.Printf("[INFO] Uncompressed contents: %s\n", fileContents)
    
        // ** Another way of reading the file **
        //
        // fileInfo, _ := handle.Stat()
        // fileContents := make([]byte, fileInfo.Size())
        // bytesRead, err := zipReader.Read(fileContents)
        // if err != nil {
        //     fmt.Println("[ERROR] Reading gzip file:", err)
        // }
        // fmt.Println("[INFO] Number of bytes read from the file:", bytesRead)
    
        closeFile(handle)
    }
    
    func openFile(fileToOpen string) (*os.File, error) {
        return os.OpenFile(fileToOpen, openFileOptions, openFilePermissions)
    }
    
    func closeFile(handle *os.File) {
        if handle == nil {
            return
        }
    
        err := handle.Close()
        if err != nil {
            fmt.Println("[ERROR] Closing file:", err)
        }
    }
    
    const openFileOptions int = os.O_CREATE | os.O_RDWR
    const openFilePermissions os.FileMode = 0660
    

    Having a full example like this should be helpful for future reference.

    0 讨论(0)
  • 2020-12-13 19:02

    For the Read part, something like the useful ioutil.ReadFile for .gz files could be :

    func ReadGzFile(filename string) ([]byte, error) {
        fi, err := os.Open(filename)
        if err != nil {
            return nil, err
        }
        defer fi.Close()
    
        fz, err := gzip.NewReader(fi)
        if err != nil {
            return nil, err
        }
        defer fz.Close()
    
        s, err := ioutil.ReadAll(fz)
        if err != nil {
            return nil, err
        }
        return s, nil   
    }
    
    0 讨论(0)
  • 2020-12-13 19:06

    Pretty much the same answer as Laurent, but with the file io:

    import (
      "bytes"
      "compress/gzip"
      "io/ioutil"
    )
    // ...
    var b bytes.Buffer
    w := gzip.NewWriter(&b)
    w.Write([]byte("hello, world\n"))
    w.Close() // You must close this first to flush the bytes to the buffer.
    err := ioutil.WriteFile("hello_world.txt.gz", b.Bytes(), 0666)
    
    0 讨论(0)
  • 2020-12-13 19:10

    Here the func for unpack gzip file to destination file:

    func UnpackGzipFile(gzFilePath, dstFilePath string) (int64, error) {
        gzFile, err := os.Open(gzFilePath)
        if err != nil {
            return 0, fmt.Errorf("Failed to open file %s for unpack: %s", gzFilePath, err)
        }
        dstFile, err := os.OpenFile(dstFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
        if err != nil {
            return 0, fmt.Errorf("Failed to create destination file %s for unpack: %s", dstFilePath, err)
        }
    
        ioReader, ioWriter := io.Pipe()
    
        go func() { // goroutine leak is possible here
            gzReader, _ := gzip.NewReader(gzFile)
            // it is important to close the writer or reading from the other end of the
            // pipe or io.copy() will never finish
            defer func(){
                gzFile.Close()
                gzReader.Close()
                ioWriter.Close()
            }()
    
            io.Copy(ioWriter, gzReader)
        }()
    
        written, err := io.Copy(dstFile, ioReader)
        if err != nil {
            return 0, err // goroutine leak is possible here
        }
        ioReader.Close()
        dstFile.Close()
    
        return written, nil
    }
    
    0 讨论(0)
  • 2020-12-13 19:12

    All the compress packages implement the same interface. You would use something like this to compress:

    var b bytes.Buffer
    w := gzip.NewWriter(&b)
    w.Write([]byte("hello, world\n"))
    w.Close()
    

    And this to unpack:

    r, err := gzip.NewReader(&b)
    io.Copy(os.Stdout, r)
    r.Close()
    
    0 讨论(0)
提交回复
热议问题