2

パッケージ「compress/gzip」を使用して、バイトのスライスを gzip しようとしています。私は bytes.Buffer に書き込んでおり、45976 バイトを書き込んでいます. 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 として選択された文字列を使用) は、Wrote: 45976、Read 32768 を提供します。

4

3 に答える 3

7

読み続けて、残りの 13208 バイトを取得します。最初の読み取りでは 32768 バイトが返され、2 回目の読み取りでは 13208 バイトが返され、3 回目の読み取りではゼロバイトと 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
于 2013-10-07T16:21:24.537 に答える
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 文字の文字列でテストした後、出力が入力とまったく同じ方法であることを確認できます。最初の部分の後に 2 番目の部分が正しく追加されます。


gzip のソース。読み取り: http://golang.org/src/pkg/compress/gzip/gunzip.go?s=4633:4683#L189

于 2013-10-07T21:59:26.513 に答える