我正在尝试从缓冲读取器压缩文件并通过字节通道传递压缩字节,但效果不佳:),这就是我到现在为止所发现的,显然这不起作用......
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的新手
答案 0 :(得分:2)
我建议使用[]byte
代替byte
。它更有效率。由于并发内存访问,可能需要通过通道发送缓冲区的副本,而不是自己发送[]byte
缓冲区。
您可以定义type ChanWriter chan []byte
并让它实现io.Writer
接口。然后将ChanWriter
传递给zlib.NewWriter
。
您可以创建一个goroutine来进行压缩,然后立即从ChanWriter
函数返回Compress
的频道。如果没有goroutine,那么函数没有理由返回一个频道,首选的返回类型是io.Reader
。
Compress
函数的返回类型应更改为chan <-BytesWithError
之类的内容。在这种情况下,ChanWriter
可以定义为type ChanWriter chan BytesWithError
。
答案 1 :(得分: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])
// ...
}
答案 2 :(得分:1)
沿着通道逐个发送字节不会特别有效。另一种可能更有用的方法是返回实现io.Reader
接口的对象,通过从原始Read()
读取块并在返回之前压缩其输出来实现io.Reader
方法。
答案 3 :(得分: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
}