how to seek in file using go

1,167 views
Skip to first unread message

hui zhang

unread,
Jan 19, 2017, 1:22:48 AM1/19/17
to golang-nuts
I am using encoding/binary to read/write (struct)data to/from file.
Some times , I need to seek in the file while reading .
how to do this in go. 
Check the code below



package main

import (
_ "bytes"
"fmt"
_ "math"

"bufio"
"encoding/binary"
"os"
)

func main() {
var pi float64
//b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40,
// 0x78, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
//buf := bytes.NewReader(b)
//err := binary.Read(buf, binary.LittleEndian, &pi)
//if err != nil {
// fmt.Println("binary.Read failed:", err)
//}
//fmt.Println(pi)
//// Output: 3.141592653589793
//err = binary.Read(buf, binary.LittleEndian, &pi)
//if err != nil {
// fmt.Println("binary.Read failed:", err)
//}
//fmt.Println(pi)
//------------------------------------------------------------
// open output file
fo, err := os.Create("./output.bin")
if err != nil {
panic(err)
}

// make a write buffer
var fl1 float64 = 3.13
var fl2 float64 = 3.14
w := bufio.NewWriter(fo)
err = binary.Write(w, binary.LittleEndian, fl1)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
err = binary.Write(w, binary.LittleEndian, fl2)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
w.Flush()
// close fo on exit and check for its returned error
if err := fo.Close(); err != nil {
panic(err)
}

//------------------------------------------------------------
fi, err := os.Open("./output.bin")
if err != nil {
panic(err)
}
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()

rd := bufio.NewReader(fi)
err = binary.Read(rd, binary.LittleEndian, &pi)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Println(pi)

fi.seek()////?????

err = binary.Read(rd, binary.LittleEndian, &pi)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Println(pi)

}

Ayan George

unread,
Jan 19, 2017, 1:43:31 AM1/19/17
to golan...@googlegroups.com


On 01/19/2017 01:22 AM, hui zhang wrote:
> I am using encoding/binary to read/write (struct)data to/from file.
> Some times , I need to seek in the file while reading .
> how to do this in go.
> Check the code below

[snip!]
>
>
> fi, err := os.Open("./output.bin")
> if err != nil {
> panic(err)
> }
> // close fi on exit and check for its returned error
> defer func() {
> if err := fi.Close(); err != nil {
> panic(err)
> }
> }()
>
> rd := bufio.NewReader(fi)
> err = binary.Read(rd, binary.LittleEndian, &pi)
> if err != nil {
> fmt.Println("binary.Read failed:", err)
> }
> fmt.Println(pi)
>
> fi.seek()////?????
>

Is File.Seek() what you're looking for or do you need something else?

https://golang.org/pkg/os/#File.Seek

-ayan

Konstantin Khomoutov

unread,
Jan 19, 2017, 1:45:16 AM1/19/17
to hui zhang, golang-nuts
On Wed, 18 Jan 2017 22:22:48 -0800 (PST)
hui zhang <fastf...@gmail.com> wrote:

[...]
> fi, err := os.Open("./output.bin")
[...]
> fi.seek()////?????

The usual drill is:

1. Get the documentation on os.Open():

$ go doc os.Open

Notice what it returns in its 1st return value has the
type *File. Since it has no "pkg." qualifier it means
that name is defined in the same package.

2. So we now read the docs on os.File:

$ go doc os.File

...and see all of its methods there, inclusing Seek().

3. So we read the docs on it:

$ go doc os.File.Seek

hui zhang

unread,
Jan 19, 2017, 1:54:31 AM1/19/17
to golang-nuts, fastf...@gmail.com
thanks all,   I use ide go to definition,  it go to the file_unix.go
in this file seek  is a private method.
So  I am confused 

在 2017年1月19日星期四 UTC+8下午2:45:16,Konstantin Khomoutov写道:

hui zhang

unread,
Jan 19, 2017, 1:59:39 AM1/19/17
to golang-nuts
fi.Seek(0, os.SEEK_SET )////?????

I set this in the code  and I expected to print 3.13 twice , but this code print 3.13 3.14
why?

   fo, err := os.Create("./output.bin")

if err != nil {
panic(err)
}

   // make a write buffer
var fl1 float64 = 3.13
var fl2 float64 = 3.14
w := bufio.NewWriter(fo)
err = binary.Write(w, binary.LittleEndian, fl1)
   if err != nil {

fmt.Println("binary.Write failed:", err)
}
err = binary.Write(w, binary.LittleEndian, fl2)
   if err != nil {

fmt.Println("binary.Write failed:", err)
}
w.Flush()
// close fo on exit and check for its returned error
if err := fo.Close(); err != nil {
panic(err)
}

//------------------------------------------------------------
   fi, err := os.Open("./output.bin")
if err != nil {
panic(err)
}
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()

rd := bufio.NewReader(fi)
err = binary.Read(rd, binary.LittleEndian, &pi)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Println(pi)

   fi.Seek(0, os.SEEK_SET )////?????

err = binary.Read(rd, binary.LittleEndian, &pi)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Println(pi)

}

在 2017年1月19日星期四 UTC+8下午2:43:31,Ayan George写道:

hui zhang

unread,
Jan 19, 2017, 2:00:33 AM1/19/17
to golang-nuts
so the file seek does not work in bufio.Read  ?

在 2017年1月19日星期四 UTC+8下午2:59:39,hui zhang写道:

Konstantin Khomoutov

unread,
Jan 19, 2017, 2:25:48 AM1/19/17
to hui zhang, golang-nuts
On Wed, 18 Jan 2017 22:54:31 -0800 (PST)
hui zhang <fastf...@gmail.com> wrote:

[...]
> > 2. So we now read the docs on os.File:
> >
> > $ go doc os.File
> >
> > ...and see all of its methods there, inclusing Seek().
> >
> > 3. So we read the docs on it:
> >
> > $ go doc os.File.Seek
> >
> thanks all, I use ide go to definition, it go to the file_unix.go
> in this file seek is a private method.
> So I am confused

That's the problem with your IDE.
Consider reporting this bug to its developers.

The `go doc` command only deals with exported symbols, so when you use
it, you're on the safe side.

Konstantin Khomoutov

unread,
Jan 19, 2017, 2:30:49 AM1/19/17
to hui zhang, golang-nuts
On Wed, 18 Jan 2017 23:00:33 -0800 (PST)
hui zhang <fastf...@gmail.com> wrote:

> so the file seek does not work in bufio.Read ?

You might need to use the Reset() method of your bufio.Reader value
before you reposition the pointer in the underlying opened file.

Please see `go doc bufio.Reader.Reset`.

But this poses the question of whether you really need buffered I/O.
May be just use io.ReadFull() helper to read data in whole chunks from
the file directly.

Ayan George

unread,
Jan 19, 2017, 2:33:28 AM1/19/17
to golan...@googlegroups.com


On 01/19/2017 02:00 AM, hui zhang wrote:
> so the file seek does not work in bufio.Read ?
>

It looks like this has been answered before:

https://groups.google.com/forum/#!topic/golang-nuts/mOvX0bmJoeI

You could also create another bufio.Reader after you seek like:

rd := bufio.NewReader(fi)
err = binary.Read(rd, binary.LittleEndian, &pi)
fmt.Println(pi)


fi.Seek(0, os.SEEK_SET )////?????

rd = bufio.NewReader(fi)
err = binary.Read(rd, binary.LittleEndian, &pi)
fmt.Println(pi)

If you look at the bufio.Reader struct, it doesn't appear to have a
notion of where it is in the file -- it just contains a buffer, read and
write positions within that buffer, etc.

-ayan

C Banning

unread,
Jan 19, 2017, 8:56:07 AM1/19/17
to golang-nuts
Why rd := bufio.NewReader(fi)?  'fi' implements io.Reader.  Try: err = binary.Read(fi, binary.LittleEndian, &pi) instead.  Then fi.Seek(...) will  manipulate your io.Reader.  [An example: https://github.com/clbanning/rfile/blob/master/reverse.go#L57.]
Reply all
Reply to author
Forward
0 new messages