透明(类似过滤器的)Go语言gzip/gunzip实现

huangapple go评论85阅读模式
英文:

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

你需要做两件事才能使其工作:

  1. 使用 io.Pipe 将读取器和写入器连接在一起 - 你不能从同一个缓冲区中读取和写入
  2. 在单独的 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

  1. Use an io.Pipe to connect the reader and writer together - you can't read and write from the same buffer
  2. 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

Playground

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.

huangapple
  • 本文由 发表于 2013年11月19日 03:46:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/20056419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定