Dear all, I am trying to get the size of an io.ReaderAt, i.e. the offset after which no more data can be read. I have some working (?) code (https://go.dev/play/p/wTouYbaJ7RG , also reproduced below), but I am not sure whether what I do is correct and the best way to do this. Some questions:
- Does the standard library provide a way to get the size of an io,ReaderAt? - Is my code correct? - Is there a better way to do this? - If a type provides not only a ReadAt() method, but also a Size() method, would it be save to assume that Size() returns how many bytes are accessible via ReadAt()? This seems to work for bytes.Reader and strings.Reader, but there may be types out there where Size() does something different? - If ReadAt(p, x) returns io.EOF for an offset x, is it then guaranteed that then ReadAt(p, y) also returns io.EOF for all y > x? Or could there be different error messages, or "files with holes", or whatnot? - Which types in the standard library provide ReadAt methods? I know of os.File, strings.Reader, and bytes.Reader. Any others? For context: this is for reading the cross reference table of PDF files, which have to be located by following some convoluted route starting *from the end* of the PDF file. Many thanks, Jochen func getSize(r io.ReaderAt) (int64, error) { if f, ok := r.(*os.File); ok { fi, err := f.Stat() if err != nil { return 0, err } return fi.Size(), nil } if b, ok := r.(*bytes.Reader); ok { return int64(b.Size()), nil } if s, ok := r.(*strings.Reader); ok { return int64(s.Size()), nil } buf := make([]byte, 1024) n, err := r.ReadAt(buf, 0) if err == io.EOF { return int64(n), nil } else if err != nil { return 0, err } lowerBound := int64(n) // all bytes before lowerBound are known to be present var upperBound int64 // at least one byte before upperBound is known to be missing for { test := 2 * lowerBound _, err := r.ReadAt(buf[:1], test-1) if err == io.EOF { upperBound = test break } else if err != nil { return 0, err } lowerBound = test } for lowerBound+1 < upperBound { test := (lowerBound + upperBound + 1) / 2 _, err := r.ReadAt(buf[:1], test-1) if err == io.EOF { upperBound = test } else if err != nil { return 0, err } else { lowerBound = test } } return lowerBound, nil } -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/aa604ac0-3542-4a9e-adef-a9eaecfd8170n%40googlegroups.com.