Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用io.Pipe()读/写golang下载zip文件_Go_Zip_Pipe_Streamreader_Writer - Fatal编程技术网

使用io.Pipe()读/写golang下载zip文件

使用io.Pipe()读/写golang下载zip文件,go,zip,pipe,streamreader,writer,Go,Zip,Pipe,Streamreader,Writer,我正在尝试使用golang中的io.Pipe()函数从zip文件中输出字节。我正在使用管道读取器读取zip中每个文件的字节,然后将这些字节流出来,并使用管道写入器在响应对象中写入字节 func main() { r, w := io.Pipe() // go routine to make the write/read non-blocking go func() { defer w.Close() bytes, err := ReadBytesforEachFil

我正在尝试使用golang中的io.Pipe()函数从zip文件中输出字节。我正在使用管道读取器读取zip中每个文件的字节,然后将这些字节流出来,并使用管道写入器在响应对象中写入字节

func main() {
  r, w := io.Pipe()
 // go routine to make the write/read non-blocking
  go func() {

    defer w.Close()

    bytes, err := ReadBytesforEachFileFromTheZip() 
    err := json.NewEncoder(w).Encode(bytes)
    handleErr(err)
  }()

这不是一个有效的实现,而是我试图实现的结构。我不想使用ioutil.ReadAll,因为文件将非常大,Pipe()将帮助我避免将所有数据带入内存。有人能用io.Pipe()帮助实现吗?

我用golang io.Pipe()实现了它。Pipewriter将字节分块写入管道,pipeReader从另一端写入。使用go例程的原因是,当从管道中同时进行读取时,具有非阻塞写入操作

注意:关闭管道编写器(w.close())以在流上发送EOF非常重要,否则它将不会关闭流

func DownloadZip() ([]byte, error) {
    r, w := io.Pipe()

    defer r.Close()
    defer w.Close()

    zip, err := os.Stat("temp.zip")
    if err != nil{
        return nil, err
    }

    go func(){

        f, err := os.Open(zip.Name())
        if err != nil {
            return

        }

        buf := make([]byte, 1024)
        for {
            chunk, err := f.Read(buf)
            if err != nil && err != io.EOF {
                panic(err)
            }
            if chunk == 0 {
                break
            }

            if _, err := w.Write(buf[:chunk]); err != nil{
                return
            }

        }

        w.Close()
    }()

    body, err := ioutil.ReadAll(r)
    if err != nil {
        return nil, err
    }
    return body, nil

}

如果有人有其他方法,请告诉我。

我使用golang io.Pipe()使其工作。Pipewriter将字节分块写入管道,pipeReader从另一端写入。使用go例程的原因是,当从管道中同时进行读取时,具有非阻塞写入操作

注意:关闭管道编写器(w.close())以在流上发送EOF非常重要,否则它将不会关闭流

func DownloadZip() ([]byte, error) {
    r, w := io.Pipe()

    defer r.Close()
    defer w.Close()

    zip, err := os.Stat("temp.zip")
    if err != nil{
        return nil, err
    }

    go func(){

        f, err := os.Open(zip.Name())
        if err != nil {
            return

        }

        buf := make([]byte, 1024)
        for {
            chunk, err := f.Read(buf)
            if err != nil && err != io.EOF {
                panic(err)
            }
            if chunk == 0 {
                break
            }

            if _, err := w.Write(buf[:chunk]); err != nil{
                return
            }

        }

        w.Close()
    }()

    body, err := ioutil.ReadAll(r)
    if err != nil {
        return nil, err
    }
    return body, nil

}


如果有人有其他方法,请告诉我。

您需要阅读整个文件
zip.NewReader
接受一个
io.ReaderAt
,这是管道无法实现的。无法使用io.Copy(zipReader,w)@mh cbon我不是100%确定,但没有io。复制是否在下面使用缓冲区?我想避免这种情况。@JimB难道没有办法避免读取整个zip文件吗?我确信当zip文件的大小很大时,没有人想把所有的数据都放到内存中。以块的形式读取字节怎么样?奇怪的是,如果它是一个常规目录,我可以使用管道吗?@psbits:zip格式就是这样工作的。中心目录位于文件末尾,因此如果不先查找文件末尾并读取目录,就无法(轻松或正确地)提取文件。您需要读取整个文件
zip.NewReader
接受一个
io.ReaderAt
,这是管道无法实现的。无法使用io.Copy(zipReader,w)@mh cbon我不是100%确定,但没有io。复制是否在下面使用缓冲区?我想避免这种情况。@JimB难道没有办法避免读取整个zip文件吗?我确信当zip文件的大小很大时,没有人想把所有的数据都放到内存中。以块的形式读取字节怎么样?奇怪的是,如果它是一个常规目录,我可以使用管道吗?@psbits:zip格式就是这样工作的。中心目录位于文件的末尾,因此如果不先查找文件的末尾并读取目录,就无法(轻松或正确地)提取文件。goroutine和pipe在这里毫无意义。您仍在同步读取文件,只是无缘无故地添加了另一个副本。@JimB您能解释一下灌浆/管道在这里是如何毫无意义的吗?go例程使管道编写器以块的形式向管道写入,而不会阻止管道读取器从另一端读取。我同意这是一种拷贝,但那不是一次拷贝所有数据吗?也许我可以使用copyN。任何读取/复制都必须分块进行,所以我不确定“一次全部”是什么意思。这里提供的是效率较低的
io.Copy
,但根本不需要复制,因为
ioutil.ReadAll
无论如何都会将整个文件读取到内存中,所以直接使用它。这很有意义。我试图使用io.Pipe()实现的是将数据块写入管道并从另一端读取,这样我就不必将所有数据一起放入内存。有什么方法可以实现@jimB?管道是不相关的。您可以使用管道将接受
io.Reader
的内容同步连接到接受
io.Writer
的内容。仅此而已。一次将整个文件读入内存或不读入内存完全取决于您——也就是说,如果您不想全部读取,请不要使用
ReadAll
。你在这里似乎有一个XY问题,你需要展示你在努力完成什么,而不是你认为你需要做什么。goroutine和pipe在这里是毫无意义的。您仍在同步读取文件,只是无缘无故地添加了另一个副本。@JimB您能解释一下灌浆/管道在这里是如何毫无意义的吗?go例程使管道编写器以块的形式向管道写入,而不会阻止管道读取器从另一端读取。我同意这是一种拷贝,但那不是一次拷贝所有数据吗?也许我可以使用copyN。任何读取/复制都必须分块进行,所以我不确定“一次全部”是什么意思。这里提供的是效率较低的
io.Copy
,但根本不需要复制,因为
ioutil.ReadAll
无论如何都会将整个文件读取到内存中,所以直接使用它。这很有意义。我试图使用io.Pipe()实现的是将数据块写入管道并从另一端读取,这样我就不必将所有数据一起放入内存。有什么方法可以实现@jimB?管道是不相关的。您可以使用管道将接受
io.Reader
的内容同步连接到接受
io.Writer
的内容。仅此而已。一次将整个文件读入内存或不读入内存完全取决于您——也就是说,如果您不想全部读取,请不要使用
ReadAll
。你在这里似乎有一个XY问题,你需要展示你正在努力完成什么,而不是你认为你需要做什么。