我正在使用一个返回io.Reader
的函数来从Internet下载文件。
我想按2048个大块来处理文件,直到由于EOF而不再可用。
io.ReadFull
函数几乎是我想要的:
buf := make([]byte, 2048)
for {
if _, err := io.ReadFull(reader, buf); err == io.EOF {
return io.ErrUnexpectedEOF
} else if err != nil {
return err
}
// Do processing on buf
}
问题是并非所有文件都是2048字节的倍数,因此最后一个块可能仅是500字节,io.ReadFull
将因此返回ErrUnexpectedEOF
,最后一块将被丢弃。
总结我想要的功能名称可能是 io.ReadFullUnlessLastChunk ,因此如果ErrUnexpectedEOF
无法填充2048个字节的原因是,则不会返回buf
该文件是EOF后例如500字节但是,在任何其他情况下,如果出现问题,都应返回ErrUnexpectedEOF
。
我该怎么做?
另一个问题是,如果我可以从网络获取256 KB的缓冲区,然后从该缓冲区中获取我需要的2048个字节,那么直接从网络中读取2048个字节似乎有很多开销。会更好。
答案 0 :(得分:1)
例如,
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func readChunks(r io.Reader) error {
if _, ok := r.(*bufio.Reader); !ok {
r = bufio.NewReader(r)
}
buf := make([]byte, 0, 2048)
for {
n, err := io.ReadFull(r, buf[:cap(buf)])
buf = buf[:n]
if err != nil {
if err == io.EOF {
break
}
if err != io.ErrUnexpectedEOF {
return err
}
}
// Process buf
fmt.Println(len(buf))
}
return nil
}
func main() {
fName := `test.file`
f, err := os.Open(fName)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
err = readChunks(f)
if err != nil {
fmt.Println(err)
return
}
}