簡體   English   中英

將 int 數組轉換為字節數組,壓縮它然后反轉它

[英]Convert int array to byte array, compress it then reverse it

我有一個很大的 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)
    }
}

您正在使用bufio.Writerbufio.Writer ,它緩沖寫入它的字節。 這意味着如果您正在使用它,您必須刷新它以確保緩沖數據能夠到達底層編寫器:

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 ,因此您顯然無法從compressionBuffer讀取壓縮數據。 不使用defer關閉 gzip 流:

if err := compressor.Close(); err != nil {
    panic(err)
}

通過這些更改,您可以對運行和輸出進行編程(在Go Playground上嘗試):

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也是完全沒有必要的,你可以開始解碼compressionBuffer本身,你可以從中讀取之前寫入的數據。

您可能已經注意到,壓縮數據比初始壓縮數據大得多。 有幾個原因: encoding/gobcompress/gzip流都有很大的開銷,並且它們(可能)只會在更大的范圍內使輸入更小(5 個整數不符合此條件)。

請檢查相關問題: Efficient Go serialization of struct to disk

對於小數組,您還可以考慮可變長度編碼,請參閱binary.PutVarint()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM