英文:
Transparent (filter-like) gzip/gunzip in Go
问题
我正在尝试,只是为了好玩,将gzip Writer直接连接到gzip Reader,这样我就可以实时地从Reader读取并写入Writer。我期望读取到与我写入的内容完全相同。我正在使用gzip,但我希望能够将这种方法应用于crypto/aes,我认为它应该非常类似,并且可以与其他的读写器一起使用,比如jpeg、png...
这是我认为最好的选项,但它并不起作用,但我希望你能理解我的意思:http://play.golang.org/p/7qdUi9wwG7
package main
import (
"bytes"
"compress/gzip"
"fmt"
)
func main() {
s := []byte("Hello world!")
fmt.Printf("%s\n", s)
var b bytes.Buffer
gz := gzip.NewWriter(&b)
ungz, err := gzip.NewReader(&b)
fmt.Println("err: ", err)
gz.Write(s)
gz.Flush()
uncomp := make([]byte, 100)
n, err2 := ungz.Read(uncomp)
fmt.Println("err2: ", err2)
fmt.Println("n: ", n)
uncomp = uncomp[:n]
fmt.Printf("%s\n", uncomp)
}
似乎gzip.NewReader(&b)
试图立即读取,然后返回EOF。
英文:
I'm trying, just for fun, to connect a gzip Writer directly to a gzip Reader, so I could write to the Writer and read from the Reader on the fly. I expected to read exactly what I wrote. I'm using gzip but I'd like to use this method also with crypto/aes, I suppose it should work very similar and it could be used with other reader/writers like jpeg, png...
This is my best option, that is not working, but I hope you can see what I mean: http://play.golang.org/p/7qdUi9wwG7
package main
import (
"bytes"
"compress/gzip"
"fmt"
)
func main() {
s := []byte("Hello world!")
fmt.Printf("%s\n", s)
var b bytes.Buffer
gz := gzip.NewWriter(&b)
ungz, err := gzip.NewReader(&b)
fmt.Println("err: ", err)
gz.Write(s)
gz.Flush()
uncomp := make([]byte, 100)
n, err2 := ungz.Read(uncomp)
fmt.Println("err2: ", err2)
fmt.Println("n: ", n)
uncomp = uncomp[:n]
fmt.Printf("%s\n", uncomp)
}
It seems that gzip.NewReader(&b)
is trying to read immediately and a EOF is returned.
答案1
得分: 5
你需要做两件事才能使其工作:
- 使用 io.Pipe 将读取器和写入器连接在一起 - 你不能从同一个缓冲区中读取和写入
- 在单独的 goroutine 中运行读取和写入。因为 gzip 的第一件事是尝试读取头部,所以如果没有另一个 goroutine 尝试写入它,你将会遇到死锁。
以下是代码示例:
func main() {
s := []byte("Hello world!")
fmt.Printf("%s\n", s)
in, out := io.Pipe()
gz := gzip.NewWriter(out)
go func() {
ungz, err := gzip.NewReader(in)
fmt.Println("err: ", err)
uncomp := make([]byte, 100)
n, err2 := ungz.Read(uncomp)
fmt.Println("err2: ", err2)
fmt.Println("n: ", n)
uncomp = uncomp[:n]
fmt.Printf("%s\n", uncomp)
}()
gz.Write(s)
gz.Flush()
}
英文:
You'll need to do two things to make it work
- Use an io.Pipe to connect the reader and writer together - you can't read and write from the same buffer
- Run the reading and writing in seperate goroutines. Because the first thing that gzip does is attempt to read the header you'll get a deadlock unless you have another go routine attemting to write it.
Here is what that looks like
func main() {
s := []byte("Hello world!")
fmt.Printf("%s\n", s)
in, out := io.Pipe()
gz := gzip.NewWriter(out)
go func() {
ungz, err := gzip.NewReader(in)
fmt.Println("err: ", err)
uncomp := make([]byte, 100)
n, err2 := ungz.Read(uncomp)
fmt.Println("err2: ", err2)
fmt.Println("n: ", n)
uncomp = uncomp[:n]
fmt.Printf("%s\n", uncomp)
}()
gz.Write(s)
gz.Flush()
}
答案2
得分: 3
使用管道。例如,
> io 包
>
> func Pipe
>
> func Pipe() (*PipeReader, *PipeWriter)
>
> Pipe
创建一个同步的内存管道。它可以用于连接期望 io.Reader 的代码和期望 io.Writer 的代码。一个端口上的读取与另一个端口上的写入相匹配,直接在两者之间复制数据;没有内部缓冲区。可以并行调用 Read 和 Write,或者与 Close 并行调用。Close 将在挂起的 I/O 完成后完成。并行调用 Read 和并行调用 Write 也是安全的:各个调用将按顺序进行。
英文:
Use a pipe. For example,
> Package io
>
> func Pipe
>
> func Pipe() (*PipeReader, *PipeWriter)
>
> Pipe
creates a synchronous in-memory pipe. It can be used to connect
> code expecting an io.Reader with code expecting an io.Writer. Reads on
> one end are matched with writes on the other, copying data directly
> between the two; there is no internal buffering. It is safe to call
> Read and Write in parallel with each other or with Close. Close will
> complete once pending I/O is done. Parallel calls to Read, and
> parallel calls to Write, are also safe: the individual calls will be
> gated sequentially.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论