我需要创建一个现有子io.Reader
的缓冲读者,但该读者必须支持寻找已经从孩子那里读取和缓冲的数据。
因此,当已经读取n
个字节时,我希望能够将读取器重置为偏移0
并再次读取该块。
不幸的是bufio.Reader
不支持搜索。
是否有支持此功能的标准阅读器,或者我是否必须自己实施?
答案 0 :(得分:4)
bufio
的目的是提供缓冲I / O.缓冲I / O用于性能,而不是时间旅行。
您只需将数据读入字节切片,然后使用bytes.Reader
进一步处理。
答案 1 :(得分:0)
我想知道是否在打开的os.File
中搜索然后使用bufio.Reset()
是一个答案,它有点但不理想。首先,bufio.Reset
的文档说它"丢弃所有缓冲的数据"但是,再次,操作系统是否还缓存最近读取的文件内容?
其次,它在bufio开始从指定文件位置开始读取和缓冲的意义上正常工作,但它不考虑扇区对齐:它一次缓冲整个缓冲区,而不管起点如何。因此,假设缓冲区大小(默认为4096)等于文件系统的簇大小,除非起始点与簇对齐,否则bufio将在每次需要读取时从2簇读取。我并不是说对性能的影响是显而易见的。事实上,通过尽可能多地提前阅读,表现可能比我的对齐可能产生的效果要好。
我认为这段代码演示了这一点,从可执行文件中读取了几个2000字节的块:
package main
import (
"bufio"
"crypto/md5"
"fmt"
"os"
)
func readBytes(r *bufio.Reader, block []byte) {
for i := 1; i < len(block); i++ {
var err error
block[i], err = r.ReadByte()
if err != nil {
panic(err)
}
}
}
func status(f *os.File, r *bufio.Reader, block []byte, what string) {
fpos, err := f.Seek(0, os.SEEK_CUR)
if err != nil {
panic(err)
}
fmt.Printf("%s: fpos=%5d, buffered=%4d, md5=%X\n", what, fpos, r.Buffered(), md5.Sum(block))
}
func main() {
f, err := os.Open(os.Args[0])
if err != nil {
panic(err)
}
defer func() { f.Close() }()
r := bufio.NewReader(f)
var block = make([]byte, 2000)
status(f, r, block, "initial")
readBytes(r, block)
status(f, r, block, "block 1")
readBytes(r, block)
status(f, r, block, "block 2")
readBytes(r, block)
status(f, r, block, "block 3")
f.Seek(2000, os.SEEK_SET) // return to start of buf1a
r.Reset(f)
readBytes(r, block)
status(f, r, block, "block 2")
readBytes(r, block)
status(f, r, block, "block 3")
readBytes(r, block)
status(f, r, block, "block 4")
}
典型输出(显示在搜索之后,文件位置不会返回到4096的倍数):
initial: fpos= 0, buffered= 0, md5=CF40A1DE3F93B4A025409B5EFA5AA210
block 1: fpos= 4096, buffered=2096, md5=C7015DD984AB85CCCBD206BA8243647D
block 2: fpos= 4096, buffered= 96, md5=E0D75F4A6DE681316515F5CD53F0D95C
block 3: fpos= 8192, buffered=2192, md5=7961B1A889E9793344374B3022314CD0
block 2: fpos= 6096, buffered=2096, md5=E0D75F4A6DE681316515F5CD53F0D95C
block 3: fpos= 6096, buffered= 96, md5=7961B1A889E9793344374B3022314CD0
block 4: fpos=10192, buffered=2192, md5=2A2F77C23EF4651E630855D9C3AA29DE