解压gzip字符串golang

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解压gzip字符串golang相关的知识,希望对你有一定的参考价值。

我有一个字符串,其中包含一个gzip压缩字符串,因此没有文件头,标准compress/gzip库抛出错误gzip: invalid header

如何在go中解压缩gzip压缩字符串?

这就是我正在尝试的

nbody := "eNorTk0uSi0BAAjRAoc="
rdata := strings.NewReader(nbody)
r,err := gzip.NewReader(rdata)
log.Println(r)
if err != nil {
    log.Fatal(err)
}
s, _ := ioutil.ReadAll(r)
fmt.Println(string(s))
答案

...我有一个包含gzip压缩字符串的字符串

nbody := "eNorTk0uSi0BAAjRAoc="

这不是“gzip压缩字符串”。这看起来像一些需要首先解码的base64编码数据。解码后,它不是gzip,而是zlib - 这与gzip(使用deflate算法压缩的内容)基本相同,但具有不同的文件头。因此,尝试使用gzip解码它将无法正常工作。

因此,下面将使用您的原始字符串,从base64解码并使用zlib(而不是gzip)解压缩它:

package main

import (
        "bytes"
        "compress/zlib"
        "encoding/base64"
        "fmt"
        "io/ioutil"
)

func main() {
        b64z := "eNorTk0uSi0BAAjRAoc="
        z, _ := base64.StdEncoding.DecodeString(b64z)
        r, _ := zlib.NewReader(bytes.NewReader(z))
        result, _ := ioutil.ReadAll(r)
        fmt.Println(string(result))  // results in "secret"
}
另一答案

nobody string不是gzip数据。 gzip有gzip标题。(https://golang.org/src/compress/gzip/gunzip.go?s=1297:1500#L42

package main

import (
    "bytes"
    "compress/gzip"
    "fmt"
    "io"
    "io/ioutil"
    "log"
)

func main() {
    nbody := "eNorTk0uSi0BAAjRAoc="

    fmt.Println("original:	", nbody)

    var buf bytes.Buffer
    err := gzipWrite(&buf, []byte(nbody))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("compressed:	", buf.String())

    var buf2 bytes.Buffer
    err = gunzipWrite(&buf2, buf.Bytes())
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("decompressed:	", buf2.String())
}

func gzipWrite(w io.Writer, data []byte) error {
    gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)
    defer gw.Close()
    gw.Write(data)
    return err
}

func gunzipWrite(w io.Writer, data []byte) error {
    gr, err := gzip.NewReader(bytes.NewBuffer(data))
    defer gr.Close()
    data, err = ioutil.ReadAll(gr)
    if err != nil {
        return err
    }
    w.Write(data)
    return nil
}
另一答案

如果您有大量输入,则可能需要使用流和自定义解码器链。

它的优点是(除了这个例子)编码输入和解码输出都不必驻留在RAM中。

package main

import (
    "bytes"
    "compress/zlib"
    "encoding/base64"
    "fmt"
    "io"
    "log"
    "os"
    "strings"
)

const nbody = "eNorTk0uSi0BAAjRAoc="

func main() {

    _, err := io.Copy(os.Stdout, decoder(strings.NewReader(nbody)))
    if err != nil {
        log.Fatalf("Error copying decoded value to stdout: %s",err)
    }
}

// This could use any io.Reader as input, for example
// a request body in http requests
func decoder(r io.Reader) io.Reader {

    // We simply set up a custom chain of Decoders
    d, err := zlib.NewReader(
        base64.NewDecoder(base64.StdEncoding, r))

    // This should only occur if one of the Decoders can not reset
    // its internal buffer. Hence, it validates a panic.
    if err != nil {
        panic(fmt.Sprintf("Error setting up decoder chain: %s", err))
    }

    // We return an io.Reader which can be used as any other
    return d

}

Run on playground

以上是关于解压gzip字符串golang的主要内容,如果未能解决你的问题,请参考以下文章

Java利用Gzip对字符串进行压缩与解压

java中使用GZIP对String进行压缩和解压

Gzip压缩与解压

字符串GZIP压缩解压

golang goroutine例子[golang并发代码片段]

对数据进行GZIP压缩和解压