我正在使用一个返回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字节的倍数,因此最后一个块可能只是例如因此,io.ReadFull
将返回ErrUnexpectedEOF
,并丢弃最后一个块。
一个函数名来总结我想要的东西可能是io.ReadFullUnlessLastChunk,所以如果ErrUnexpectedEOF
不能用2048字节填充的原因,则不返回buf
,例如,文件是EOF之后的EOF。 500字节。但是,在任何其他情况下,ErrUnexpectedEOF
应该在问题发生时返回。
我该怎么做才能做到这一点?
另一个问题是直接从网络读取2048字节似乎有很多开销,如果我可以从网络获得256 KB到缓冲区,然后从该缓冲区取得我需要的2048字节,那会更好。
例如,
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
}
}