我正在尝试使用“compress / gzip”包来gzip一片字节。我正在写一个bytes.Buffer,我正在写45976字节,当我尝试使用gzip.reader和读取器函数解压缩内容时 - 我发现并非所有内容都被恢复。 bytes.buffer有一些限制吗?这是通过或改变这种方式的方法吗?这是我的代码(编辑):
func compress_and_uncompress() {
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
i,err := w.Write([]byte(long_string))
if(err!=nil){
log.Fatal(err)
}
w.Close()
b2 := make([]byte, 80000)
r, _ := gzip.NewReader(&buf)
j, err := r.Read(b2)
if(err!=nil){
log.Fatal(err)
}
r.Close()
fmt.Println("Wrote:", i, "Read:", j)
}
测试输出(选择字符串为long_string)会给出 写道:45976,阅读32768
答案 0 :(得分:5)
继续阅读以获得剩余的13208个字节。第一个读取返回32768个字节,第二个读取返回13208个字节,第三个读取返回零个字节和EOF。
例如,
package main
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"log"
)
func compress_and_uncompress() {
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
i, err := w.Write([]byte(long_string))
if err != nil {
log.Fatal(err)
}
w.Close()
b2 := make([]byte, 80000)
r, _ := gzip.NewReader(&buf)
j := 0
for {
n, err := r.Read(b2[:cap(b2)])
b2 = b2[:n]
j += n
if err != nil {
if err != io.EOF {
log.Fatal(err)
}
if n == 0 {
break
}
}
fmt.Println(len(b2))
}
r.Close()
fmt.Println("Wrote:", i, "Read:", j)
}
var long_string string
func main() {
long_string = string(make([]byte, 45976))
compress_and_uncompress()
}
输出:
32768
13208
Wrote: 45976 Read: 45976
答案 1 :(得分:2)
使用ioutil.ReadAll。 io.Reader的合同说它不必返回所有数据,并且有充分的理由不与内部缓冲区的大小有关。 ioutil.ReadAll
的作用类似于io.Reader,但会读到EOF。
例如(未经测试)
import "io/ioutil"
func compress_and_uncompress() {
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
i,err := w.Write([]byte(long_string))
if err!=nil {
log.Fatal(err)
}
w.Close()
r, _ := gzip.NewReader(&buf)
b2, err := ioutil.ReadAll(r)
if err!=nil {
log.Fatal(err)
}
r.Close()
fmt.Println("Wrote:", i, "Read:", len(b2))
}
答案 2 :(得分:1)
如果从gzip.NewReader读取的内容未返回整个预期的切片。您可以继续重新阅读,直到您收到缓冲区中的所有数据。
关于你的问题,如果你重新读取后续的读取没有附加到切片的末尾,而是在开头;答案可以在gzip的Read函数的实现中找到,其中包括
208 z.digest.Write(p[0:n])
这将导致字符串开头的“追加”。
这可以通过这种方式解决
func compress_and_uncompress(long_string string) {
// Writer
var buf bytes.Buffer
w := gzip.NewWriter(&buf)
i,err := w.Write([]byte(long_string))
if(err!=nil){
log.Fatal(err)
}
w.Close()
// Reader
var j, k int
b2 := make([]byte, 80000)
r, _ := gzip.NewReader(&buf)
for j=0 ; ; j+=k {
k, err = r.Read(b2[j:]) // Add the offset here
if(err!=nil){
if(err != io.EOF){
log.Fatal(err)
} else{
break
}
}
}
r.Close()
fmt.Println("Wrote:", i, "Read:", j)
}
结果将是:
Wrote: 45976 Read: 45976
在使用45976个字符串进行测试后,我可以确认输出与输入完全相同,其中第二部分正确地附加在第一部分之后。
gzip的来源。阅读:http://golang.org/src/pkg/compress/gzip/gunzip.go?s=4633:4683#L189