如何连接io.Reader和io.Writer?

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

How do I connect io.Reader and io.Writer?

问题

我正在编写一个长时间运行的任务,它会多次从MongoDB中获取数据(使用mgo库)。然后使用这个模块将数据写入xlsx文件。然后使用os.Open再次读取文件,并将其存储到我的FTP服务器上。

Stor函数消耗了大量内存,所以我认为应该有一种方法可以不保存文件,而是直接将数据从xlsx.Write传递给ftp.Store函数(如果可以同时进行流式传输将是完美的,因为在将它们发送到Stor函数之前,我不必在服务器内存中保存所有文档)。

以下是这些函数的原型:

func (f *File) Write(writer io.Writer) (err error) xlsl

func (ftp *FTP) Stor(path string, r io.Reader) (err error) ftp

英文:

I'm writing a long running task which fetch from mongodb (using mgo) multiple times. Then write it to an xlsx file using this module. Then read it again using os.Open then store it to my ftp server.

Stor function consume my memory so much, So I think there should be a way not to save file but pass my data from xlsx.Write to ftp.Store directly. (If I can stream simultaneously would be perfect because I don't have to hold all of my documents in server's memory before send them to Stor function)

These are prototype of the functions

func (f *File) Write(writer io.Writer) (err error) xlsl

func (ftp *FTP) Stor(path string, r io.Reader) (err error) ftp

答案1

得分: 29

你想使用io.Pipe。你可以这样做:

reader, writer := io.Pipe()
errChan := make(chan error)
go func() {
    errChan <- myFTP.Stor(path, reader)
}()
err := myXLS.Write(writer)
// 处理错误
err = <-errChan
// 处理错误

如果xlsx.Write返回一个错误但没有关闭写入器,你可能想要使用writer.CloseWithError(err)来关闭写入器。

英文:

You want to use io.Pipe. You can do:

reader, writer := io.Pipe()
errChan := make(chan error)
go func() {
    errChan &lt;- myFTP.Stor(path, reader)
}()
err := myXLS.Write(writer)
// handle err
err = &lt;-errChan
// handle err

You might want to writer.CloseWithError(err) if xlsx.Write returns an error without closing the writer.

答案2

得分: 2

你可以使用bytes.Buffer

func uploadFileToQiniu(file *xlsx.File) (key string, err error) {
    key = fmt.Sprintf("%s.xlsx", util.SerialNumber())
    log.Debugf("file key is %s", key)

    log.Debug("start to write file to a writer")
    buf := new(bytes.Buffer)
    err = file.Write(buf)
    if err != nil {
        log.Errorf("error caught when writing file: %v", err)
        return
    }

    size := int64(buf.Len())
    log.Debugf("file size is %d", size)
    err = Put(key, size, buf)
    if err != nil {
        log.Errorf("error caught when uploading file: %v", err)
    }
    return key, nil
}

<!-- -->

func Put(key string, size int64, reader io.Reader) error {}
英文:

you can use bytes.Buffer:

func uploadFileToQiniu(file *xlsx.File) (key string, err error) {
	key = fmt.Sprintf(&quot;%s.xlsx&quot;, util.SerialNumber())
	log.Debugf(&quot;file key is %s&quot;, key)

	log.Debug(&quot;start to write file to a writer&quot;)
	buf := new(bytes.Buffer)
	err = file.Write(buf)
	if err != nil {
		log.Errorf(&quot;error caught when writing file: %v&quot;, err)
		return
	}

	size := int64(buf.Len())
	log.Debugf(&quot;file size is %d&quot;, size)
	err = Put(key, size, buf)
	if err != nil {
		log.Errorf(&quot;error caught when uploading file: %v&quot;, err)
	}
	return key, nil
}

<!-- -->

func Put(key string, size int64, reader io.Reader) error {}

huangapple
  • 本文由 发表于 2015年7月7日 12:35:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/31259812.html
匿名

发表评论

匿名网友

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

确定