Go 将int数组转换为byte数组,压缩它,然后反转它

Go 将int数组转换为byte数组,压缩它,然后反转它,go,compression,gzip,eof,gob,Go,Compression,Gzip,Eof,Gob,我有一个大的int数组,我想保存在文件系统上。我的理解是,存储这样的内容的最佳方法是使用包将其转换为字节数组,然后使用压缩。 当我再次需要它时,我会反转这个过程。我非常确定我正确地存储了它,但是用EOF恢复它失败了。长话短说,下面我有一些示例代码来演示这个问题。(此处为游乐场链接)。 我不认为需要gob,但是仔细阅读一下,将其存储为字节数组似乎比int数组更有效,但这可能不是真的。谢谢 package main import ( "bufio" "bytes" "com

我有一个大的int数组,我想保存在文件系统上。我的理解是,存储这样的内容的最佳方法是使用包将其转换为字节数组,然后使用压缩。 当我再次需要它时,我会反转这个过程。我非常确定我正确地存储了它,但是用EOF恢复它失败了。长话短说,下面我有一些示例代码来演示这个问题。(此处为游乐场链接)。 我不认为需要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)
    }
}
主程序包
进口(
“布菲奥”
“字节”
“压缩/gzip”
“编码/gob”
“fmt”
)
func main(){
arry:=[]int{1,2,3,4,5}
//现在把这个吞下去
var indexBuffer bytes.Buffer
writer:=bufio.NewWriter(&indexBuffer)
编码器:=gob.NewEncoder(写入程序)
如果错误:=encoder.Encode(arry);错误!=nil{
恐慌(错误)
}
//现在压缩它
var压缩缓冲区字节。缓冲区
压缩器:=gzip.NewWriter(&compressionBuffer)
compressor.Write(indexBuffer.Bytes())
延迟压缩程序。关闭()
// 顾名思义,您正在使用它来缓冲写入它的字节。这意味着,如果您正在使用它,您必须刷新它,以确保缓冲数据到达底层写入程序:

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
(因此您甚至不必刷新):

下一个错误是如何关闭gzip流:

defer compressor.Close()
只有当封闭函数(函数
main()
时,才会发生延迟关闭返回,不早一秒。但到那时,您已经想读取压缩数据,但该数据可能仍然位于的内部缓存中,而不是
compressionBuffer
,因此您显然无法从
compressionBuffer
读取压缩数据。请关闭gzip流,而不使用
defer

if err := compressor.Close(); err != nil {
    panic(err)
}
通过这些更改,您可以运行和输出程序(在上尝试):

作为旁注:
buf:=bytes.NewBuffer(compressionBuffer.bytes())
–此
buf
也是完全不必要的,您可以开始解码
compressionBuffer
本身,您可以从中读取以前写入它的数据

正如您可能已经注意到的,压缩数据比初始压缩数据大得多。有几个原因:和流都有很大的开销,并且它们(可能)只会在更大的范围内使输入更小(5整数不符合此条件)

请检查相关问题:


对于小数组,您也可以考虑,参见.p/>您的问题是什么?是否<代码> GOB <代码>是适当的或更有效的?还是您的代码有一些具体的问题?当我尝试在GOB->压缩->扩展-> GOB之后恢复初始INT数组时,我得到一个EOF,即它没有恢复到原来的int数组。hanks很喜欢。正在阅读有关flush的内容,但将从进程中删除写入程序。编辑:有没有办法知道压缩何时变得有价值?是否需要使用gob来保存不值得压缩的[]int?@amlwwalker当压缩变得“有价值”时:measure.它取决于输入。某些输入可能会被更好地压缩。
gob
不是必需的,实际上它只会增加计算和空间开销。如果您仍然想压缩,只需使用
编码/二进制
将整数转换为字节(您可以将其写入
gzip
流)。还要注意的是,您不应该使用
int
,因为它的大小取决于体系结构,而应该固定大小的整数,如
int32
int64
。很酷,所以去掉gob听起来是个好主意。我想我已经很接近了,它使用编码/二进制将其转换回[]压缩后的int64对我来说是失败的-我在读入[]int64后得到一个空数组。你能看一下吗?嗯,问题可能是我需要先知道数组的大小?gob可以处理吗?编码/二进制不能?-编辑-是的,似乎就是这样。嗯,这意味着我需要保留原始[]的长度吗那么int64还是可以动态“计算”出来?@amlwwalker类型
[]int64
的值的长度是不固定的,因此您必须自己保存长度。
gob
会为您解决这个问题。
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]