I want to create 2 scanners from the same reader r
. But when calling Scan()
from the first scanner, it drains the buffer from r
, so the second scanner is reading a zero buffer. Is that a common behavior? How to fix it so that the second scanner properly reads from the original r
?
r := bytes.NewReader([]byte("ninebytes"))
fmt.Println(r.Len()) // 9
sc1 := bufio.NewScanner(r)
sc1.Scan()
fmt.Printf("scanner1: %s
", 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
", sc2.Text()) // scanner2:
Here's an example at play golang
This is what I'm trying to do: read a specific line from a file, but when calling the function a second time, r
is drained.
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()
}
Reading a reader is in general a destructive action; particularly with http request bodies.
Instead you can create a tee reader, which is modelled on the unix tee
command.
Modifying the example you've given:
r := bytes.NewReader([]byte("ninebytes"))
var buf bytes.Buffer
tee := io.TeeReader(r, &buf)
sc1 := bufio.NewScanner(tee)
sc1.Scan()
fmt.Printf("scanner1: %s
", sc1.Text())
sc2 := bufio.NewScanner(&buf)
sc2.Scan()
fmt.Printf("scanner2: %s
", sc2.Text())
Using a tee reader, as you read from r
it will write a copy of those bytes to buf
, which you can use again in the second scanner.