2

バッファリングされたリーダーからファイルを圧縮し、圧縮されたバイトをバイトチャネルを介して渡そうとしていますが、結果は良くありません:)、これが私が今まで思いついたことです。明らかにこれは機能しません...

func Compress(r io.Reader) (<-chan byte) {
    c := make(chan byte)
    go func(){
        var wBuff bytes.Buffer
        rBuff := make([]byte, 1024)
        writer := zlib.NewWriter(*wBuff)
        for {
            n, err := r.Read(rBuff)
            if err != nil && err != io.EOF { panic(err) }
            if n == 0 { break }
            writer.Write(rBuff) // Compress and write compressed data
            // How to send written compressed bytes through channel?
            // as fas as I understand wBuff will eventually contain
            // whole compressed data?
        }
        writer.Close()
        close(c) // Indicate that no more data follows
    }()
    return c
}

私はGoに非常に慣れていないので、ご容赦ください

4

4 に答える 4

3

[]byteの代わりに使用することをお勧めしますbyte。より効率的です。並行メモリ アクセスのため、バッファ自体を送信するのではなく、チャネルを介してバッファのコピーを送信する必要がある場合があります。[]byte

を定義して、インターフェイスtype ChanWriter chan []byteを実装させることができます。io.Writer次に、 を に渡しChanWriterますzlib.NewWriter

圧縮を行うためのゴルーチンを作成し、すぐに関数ChanWriterから のチャネルを返すことができますCompress。ゴルーチンがない場合、関数がチャネルを返す理由はなく、推奨される戻り値の型はio.Readerです。

関数の戻り値の型を のCompressように変更する必要がありますchan <-BytesWithError。この場合ChanWriter、 として定義できますtype ChanWriter chan BytesWithError

于 2013-05-22T05:41:23.993 に答える
2

チャネルを介してバイトを 1 つずつ送信することは、特に効率的ではありません。io.Readerより便利な別のアプローチは、インターフェイスを実装するオブジェクトを返すことです。Read()元のブロックを読み取ってメソッドを実装し、io.Readerその出力を圧縮してから返します。

于 2013-05-21T09:37:58.293 に答える
1

. の場合でも、ステートメントは常にバイトwriter.Write(rBuff)を書き込みます。len(rBuff)n != len(rBuff)

writer.Write(rBuff[:n])

また、あなたのReadループは

for {
    n, err := r.Read(rBuff)
    if err != nil && err != io.EOF {
        panic(err)
    }
    if n == 0 {
        break
    }
    writer.Write(rBuff[:n])
    // ...
}

これはと同等です

for {
    n, err := r.Read(rBuff)
    if err != nil && err != io.EOF {
        panic(err)
    }
    // !(err != nil && err != io.EOF)
    // !(err != nil) || !(err != io.EOF)
    // err == nil || err == io.EOF
    if err == nil || err == io.EOF {
        if n == 0 {
            break
        }
    }
    writer.Write(rBuff[:n])
    // ...
}

ループは途中で終了しますif err == nil && if n == 0

代わりに、

for {
    n, err := r.Read(rBuf)
    if err != nil {
        if err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }
    }
    writer.Write(rBuf[:n])
    // ...
}
于 2013-05-21T03:29:02.460 に答える
0

わかりました、私は実用的な解決策を見つけました: (それを改善できる場所を自由に示してください。または、何か間違ったことをしている可能性がありますか?)

func Compress(r io.Reader) (<-chan byte) {
    c := make(chan byte)

    go func(){
        var wBuff bytes.Buffer
        rBuff := make([]byte, 1024)
        writer := zlib.NewWriter(&wBuff)
        for {
            n, err := r.Read(rBuff)

            if err != nil {
                if err != io.EOF {
                    panic(err)
                }
                if n == 0 {
                    break
                }
            }

            writer.Write(rBuff[:n])

            for _, v := range wBuff.Bytes() {
                c <- v
            }

            wBuff.Truncate(0)
        }

        writer.Close()

        for _, v := range wBuff.Bytes() {
            c <- v
        }

        close(c) // Indicate that no more data follows
    }()

    return c
}
于 2013-05-21T01:10:54.060 に答える