我有一个大的int数组,我想保留在文件系统上。我的理解是,存储此类内容的最佳方法是使用gob包将其转换为字节数组,然后使用gzip对其进行压缩。 当我再次需要它时,我将撤消该过程。我相当确定我可以正确存储它,但是使用EOF无法恢复它。长话短说,下面有一些示例代码演示了该问题。 (此处https://play.golang.org/p/v4rGGeVkLNh的游乐场链接)。 我不认为需要gob,但是阅读它似乎将它存储为字节数组比存储int数组更有效,但这可能并非正确。谢谢!
package main
import (
"bufio"
"bytes"
"compress/gzip"
"encoding/gob"
"fmt"
)
func main() {
arry := []int{1, 2, 3, 4, 5}
//now gob this
var indexBuffer bytes.Buffer
writer := bufio.NewWriter(&indexBuffer)
encoder := gob.NewEncoder(writer)
if err := encoder.Encode(arry); err != nil {
panic(err)
}
//now compress it
var compressionBuffer bytes.Buffer
compressor := gzip.NewWriter(&compressionBuffer)
compressor.Write(indexBuffer.Bytes())
defer compressor.Close()
//<--- I think all is good until here
//now decompress it
buf := bytes.NewBuffer(compressionBuffer.Bytes())
fmt.Println("byte array before unzipping: ", buf.Bytes())
if reader, err := gzip.NewReader(buf); err != nil {
fmt.Println("gzip failed ", err)
panic(err)
} else {
//now ungob it...
var intArray []int
decoder := gob.NewDecoder(reader)
defer reader.Close()
if err := decoder.Decode(&intArray); err != nil {
fmt.Println("gob failed ", err)
panic(err)
}
fmt.Println("final int Array content: ", intArray)
}
}
答案 0 :(得分:1)
您正在使用bufio.Writer
-顾名思义,其中写入了 buffers 个字节。这意味着,如果您正在使用它,则必须 flush 以确保缓冲的数据进入基础编写器:
writer := bufio.NewWriter(&indexBuffer)
encoder := gob.NewEncoder(writer)
if err := encoder.Encode(arry); err != nil {
panic(err)
}
if err := writer.Flush(); err != nil {
panic(err)
}
尽管完全不需要使用bufio.Writer
,因为您已经在写内存缓冲区(bytes.Buffer
)了,所以跳过它,直接写到bytes.Buffer
(因此您甚至不必冲洗):
var indexBuffer bytes.Buffer
encoder := gob.NewEncoder(&indexBuffer)
if err := encoder.Encode(arry); err != nil {
panic(err)
}
下一个错误是您如何关闭gzip流:
defer compressor.Close()
仅当封闭函数(main()
函数)返回时才发生此延迟关闭,而不是更早。但是到那时,您已经想读取压缩后的数据,但是它可能仍位于gzip.Writer
的内部缓存中,而不是compressionBuffer
的内部缓存中,因此您显然无法从{读取压缩的数据。 {1}}。在不使用compressionBuffer
的情况下关闭gzip流:
defer
通过这些更改,您可以对程序进行运行和输出(在Go Playground上进行尝试):
if err := compressor.Close(); err != nil {
panic(err)
}
作为旁注:byte array before unzipping: [31 139 8 0 0 0 0 0 0 255 226 249 223 200 196 200 244 191 137 129 145 133 129 129 243 127 19 3 43 19 11 27 7 23 32 0 0 255 255 110 125 126 12 23 0 0 0]
final int Array content: [1 2 3 4 5]
–这个buf := bytes.NewBuffer(compressionBuffer.Bytes())
也是完全没有必要的,您可以开始解码buf
本身,可以从先前写入的数据中读取数据
您可能已经注意到,压缩数据比初始压缩数据大得多。原因有几个:encoding/gob
和compress/gzip
流都具有相当大的开销,并且它们(可能)只会使输入在更大的范围内变小(5个int数不符合此条件)。
请检查相关问题:Efficient Go serialization of struct to disk
对于小型阵列,您还可以考虑使用variable-length encoding,请参阅binary.PutVarint()
。