Is there an implementation of io.ReaderAt
that can be created from an implementation of io.Reader
without first being read into a []byte
or string
?
You may use it when you have Read and Close methods, an example to show that you may use one common function to work with different types using io.ReadCloser : package main import ( "fmt" "io" "log" "os" ) func main() { f, err := os.Open("./main.go") if err != nil { log.Fatal(err) } doIt(f) doIt(os.Stdin) } func doIt( ...
The io.Reader interface is used by many packages in the Go standard library and it represents the ability to read a stream of data. More specifically allows you to read data from something that implements the io.Reader interface into a slice of bytes.
It returns the number of bytes copied and an error if fewer bytes were read. The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, ReadFull returns ErrUnexpectedEOF.
Something like the below. Note bytes.Reader
implements the ReadAt(...)
method/function: https://golang.org/pkg/bytes/#Reader.ReadAt. So the line bytes.NewReader
is esssentially what you are looking for.
Getting a bytes.Reader
:
var ioReader io.Reader
...
buff := bytes.NewBuffer([]byte{})
size, err := io.Copy(buff, ioReader)
if err != nil {
return err
}
reader := bytes.NewReader(buff.Bytes())
// Do something with `reader`
Yes, this is possible. As mentioned in my comment above, the implementation is limited in that you cannot seek backward nor can you re-read a section that has already been read.
Here is a example implementation:
type unbufferedReaderAt struct {
R io.Reader
N int64
}
func NewUnbufferedReaderAt(r io.Reader) io.ReaderAt {
return &unbufferedReaderAt{R: r}
}
func (u *unbufferedReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
if off < u.N {
return 0, errors.New("invalid offset")
}
diff := off - u.N
written, err := io.CopyN(ioutil.Discard, u.R, diff)
u.N += written
if err != nil {
return 0, err
}
n, err = u.R.Read(p)
u.N += int64(n)
return
}
Example usage:
s := strings.NewReader("hello world")
var b [5]byte
ura := NewUnbufferedReaderAt(s)
if _, err := ura.ReadAt(b[:], 0); err != nil {
panic(err)
}
fmt.Printf("%s\n", b[:]) // prints "hello"
/*
if _, err := ura.ReadAt(b[:], 0); err != nil {
panic(err) // panics
}
fmt.Printf("%s\n", b[:])
*/
if _, err := ura.ReadAt(b[:], 6); err != nil {
panic(err)
}
fmt.Printf("%s\n", b[:]) // prints "world"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With