解压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
}
以上是关于解压gzip字符串golang的主要内容,如果未能解决你的问题,请参考以下文章