bytes.Buffer and bufio.Reader are no seekers?

6,668 views
Skip to first unread message

Ingo Oeser

unread,
May 2, 2013, 10:15:52 AM5/2/13
to golan...@googlegroups.com
Hi there,

is there any reason the in-memory streams bytes.Buffer and bufio.Reader support no Seek()?

Just wondered about it, because it would be very handy for unit tests and benchmarks mocking out file system accesses.

So I did sth. like this to test it:



package main

import (
"bytes"
"fmt"
"io"
"os"
)

type SeekingBuffer struct {
b      []byte
buffer *bytes.Buffer
offset int64
size   int64
}

func NewSeekingBuffer(b []byte) *SeekingBuffer {
if b == nil {
return nil
}
return &SeekingBuffer{
b:      b,
buffer: bytes.NewBuffer(b),
offset: 0,
}
}

func (fb *SeekingBuffer) Read(p []byte) (n int, err error) {
n, err = fb.buffer.Read(p)
fb.offset += int64(n)
return n, err
}

func (fb *SeekingBuffer) Seek(offset int64, whence int) (ret int64, err error) {
var newoffset int64
switch whence {
case 0:
newoffset = offset
case 1:
newoffset = fb.offset + offset
case 2:
newoffset = int64(len(fb.b)) - offset
}
if newoffset == fb.offset {
return newoffset, nil
}
fb.buffer = bytes.NewBuffer(fb.b[newoffset:])
fb.offset = newoffset
return fb.offset, nil
}

func main() {
fb := NewSeekingBuffer([]byte("Hello, playground"))
pos, err := fb.Seek(0, 0)
fmt.Println("pos = ", pos, ", error = ", err)
pos, err = fb.Seek(7, 0)
fmt.Println("pos = ", pos, ", error = ", err)
io.Copy(os.Stdout, fb)

}

Andrew Gerrand

unread,
May 2, 2013, 10:17:39 AM5/2/13
to Ingo Oeser, golang-nuts

On 2 May 2013 10:15, Ingo Oeser <night...@googlemail.com> wrote:
is there any reason the in-memory streams bytes.Buffer and bufio.Reader support no Seek()?

Because they both throw data away after it has been read. They're for potentially boundless streams of data, not in-memory files.

If you want the latter, see bytes.Reader: http://golang.org/pkg/bytes/#Reader

Ingo Oeser

unread,
May 2, 2013, 10:29:38 AM5/2/13
to golan...@googlegroups.com, Ingo Oeser
Cool thanks! Totally forgot about this bytes.Reader :-)

Guillaume LE STUM

unread,
Aug 31, 2016, 8:26:10 AM8/31/16
to golang-nuts
I just ran into this as well, when buffering an io.ReadSeeker such as os.File it would be useful to have a bufio.ReadSeeker.
I could work around it by calling Seek on the source os.File and using bufio.Reader.Reset(...) but this is wasteful when seeked data is already buffered
Reply all
Reply to author
Forward
0 new messages