当前位置: > > > > 精确读取 n 个字节,除非 EOF?
精确读取 n 个字节,除非 EOF?
来源:stackoverflow
2024-04-28 08:57:34
0浏览
收藏
在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天米云就整理分享《精确读取 n 个字节,除非 EOF?》,聊聊,希望可以帮助到正在努力赚钱的你。
问题内容
我正在使用一个返回 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,因此如果buf无法填充2048字节的原因是文件在例如之后是eof,则不会返回errunexpectedeof。 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
}
}
理论要掌握,实操不能落!以上关于《精确读取 n 个字节,除非 EOF?》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注米云公众号吧!
