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接口。然后通过ChanWriterto zlib.NewWriter

您可以创建一个 goroutine 来进行压缩,然后立即从您的函数中返回ChanWriter' 通道。Compress如果没有 goroutine,则函数没有理由返回通道,首选返回类型是io.Reader.

函数的返回类型Compress应更改为类似chan <-BytesWithError. 在这种情况下ChanWriter可以定义为type ChanWriter chan BytesWithError

于 2013-05-22T05:41:23.993 回答
2

在通道上逐个发送字节不会特别有效。另一种可能更有用的方法是返回实现io.Reader接口的对象,Read()通过从原始块中读取块io.Reader并在返回之前压缩其输出来实现该方法。

于 2013-05-21T09:37:58.293 回答
1

Your writer.Write(rBuff) statement always writes len(rBuff) bytes, even when n != len(rBuff).

writer.Write(rBuff[:n])

Also, your Read loop is

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

which is equivalent to

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])
    // ...
}

The loop exits prematurely if err == nil && if n == 0.

Instead, write

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 回答