I have a string which contains a gzip compressed string, therefore there's no file headers, standard compress/gzip
library throws error gzip: invalid header
How can I decompress a gzip compressed string in go?
This is what I'm trying
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))
... I have a string which contains a gzip compressed string
nbody := "eNorTk0uSi0BAAjRAoc="
This is not a "gzip compressed string". This looks like some base64 encoded data which need to be decoded first. After decoding it is not gzip either but zlib - which is basically the same as gzip (content compressed with deflate algorithm) but with a different file header. Therefore trying to decode it with gzip will not work.
The following will therefore take your original string, decode it from base64 and decompress it using zlib (not 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"
}
If you have large inputs, you might want to use streams and a custom chain of decoders instead.
It has the advantage that (except for this example) neither the encoded input nor the decoded output has to reside in 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
}