我是 Go 新手,不知道如何利用这个compress/gzip包来发挥我的优势。基本上,我只是想写一些东西到一个文件中,gzip 它并通过另一个脚本直接从压缩格式中读取它。如果有人能给我一个如何做到这一点的例子,我将不胜感激。
			
			39380 次
		
6 回答
            56        
        
		
所有压缩包都实现相同的接口。你会使用这样的东西来压缩:
var b bytes.Buffer
w := gzip.NewWriter(&b)
w.Write([]byte("hello, world\n"))
w.Close()
这要解压:
r, err := gzip.NewReader(&b)
io.Copy(os.Stdout, r)
r.Close()
    于 2013-06-03T06:00:35.230   回答
    
    
            10        
        
		
与 Laurent 的答案几乎相同,但使用文件 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)
    于 2013-10-25T16:17:47.960   回答
    
    
            9        
        
		
对于读取部分,对于.gz文件有用的ioutil.ReadFile可能是:
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   
}
    于 2014-05-13T15:10:09.367   回答
    
    
            6        
        
		
这里是解压 gzip 文件到目标文件的函数:
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
}
    于 2016-07-12T09:44:04.153   回答
    
    
            2        
        
		
我决定结合其他答案的想法,只提供一个完整的示例程序。显然,有许多不同的方法可以做同样的事情。这只是一种方式:
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
拥有这样的完整示例应该有助于将来的参考。
于 2015-08-14T20:02:29.467   回答
    
    
            1        
        
		
压缩任何接口类型的 Go 对象作为输入
func compress(obj interface{}) ([]byte, error) {
    var b bytes.Buffer
    objBytes, err := json.Marshal(obj)
    if err != nil {
        return nil, err
    }
    gz := gzip.NewWriter(&b)
    defer gz.Close() //NOT SUFFICIENT, DON'T DEFER WRITER OBJECTS
    if _, err := gz.Write(objBytes); err != nil {
        return nil, err
    }
    // NEED TO CLOSE EXPLICITLY
    if err := gz.Close(); err != nil {
        return nil, err
    }
    return b.Bytes(), nil
}
要解压缩相同,
func decompress(obj []byte) ([]byte, error) {
    r, err := gzip.NewReader(bytes.NewReader(obj))
    if err != nil {
        return nil, err
    }
    defer r.Close()
    res, err := ioutil.ReadAll(r)
    if err != nil {
        return nil, err
    }
    return res, nil
}
注意,如果写入后不关闭 Writer 对象,则ioutil.ReadAll(r)返回io.EOF或io.ErrUnexpectedEOF 。我假设 Close() 上的 defer 会正确关闭对象,但不会。不要推迟 writer 对象。
于 2021-05-31T13:30:12.087   回答