当前位置: > > > > 精确读取 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?》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注公众号吧!