首页 > 解决方案 > bufio.NewScanner(r) 从 r 调用 Scan() 耗尽缓冲区

问题描述

我想从同一个阅读器创建 2 个扫描仪r。但是当Scan()从第一个扫描仪调用时,它会从 中耗尽缓冲区r,因此第二个扫描仪正在读取零缓冲区。这是一种常见的行为吗?如何修复它以使第二台扫描仪正确读取原件r

r := bytes.NewReader([]byte("ninebytes"))
fmt.Println(r.Len()) // 9
sc1 := bufio.NewScanner(r)
sc1.Scan()
fmt.Printf("scanner1: %s\n", sc1.Text()) // scanner1: ninebytes

// i want create new scanner from r too
fmt.Println(r.Len()) // 0
sc2 := bufio.NewScanner(r)
sc1.Scan()
fmt.Printf("scanner2: %s\n", sc2.Text()) // scanner2: 

这是一个玩 golang的例子

这就是我想要做的:从文件中读取特定的行,但是当第二次调用该函数时,r它被耗尽了。

func readLineScanner(r io.Reader, lineNum int) ([]byte, error) {
    sc := bufio.NewScanner(r)
    lastLine := 0
    for sc.Scan() {
        lastLine++
        if lastLine == lineNum {
            break
        }
    }
    return sc.Bytes(), sc.Err()
}

标签: goio

解决方案


阅读读者通常是一种破坏性的行为。特别是对于 http 请求主体。

tee相反,您可以创建一个以 unix命令为模型的 tee 阅读器。

链接到文档

修改您给出的示例:

r := bytes.NewReader([]byte("ninebytes"))

var buf bytes.Buffer
tee := io.TeeReader(r, &buf)

sc1 := bufio.NewScanner(tee)
sc1.Scan()
fmt.Printf("scanner1: %s\n", sc1.Text())

sc2 := bufio.NewScanner(&buf)
sc2.Scan()
fmt.Printf("scanner2: %s\n", sc2.Text())

使用 tee 阅读器,当您从中读取时r,会将这些字节的副本写入buf,您可以在第二个扫描仪中再次使用它。


推荐阅读