-1

Similar to this question, what is the idiomatic way to process a file one byte at a time in go?

Put another way, is there a better way to write the following?

file, err := ioutil.ReadFile(filename)
file_string = string(file)
for i, c := range file_string {
    // -snip-
}
Community
  • 1
  • 1
Bijan
  • 149
  • 5
  • 5
    This isn't reading the file one byte at a time. This is reading the whole file, converting it to a string, and iterating through it rune by rune (not byte by byte). Do you want to read the file one byte at a time, or process it one byte at a time? – Burak Serdar Apr 30 '20 at 16:23
  • 3
    Reading one byte at a time is extremely inefficient, you probably want something like: [`Reader.ReadByte`](https://pkg.go.dev/bufio?tab=doc#Reader.ReadByte) – JimB Apr 30 '20 at 16:26

1 Answers1

6

You're reading the entire file as a string (not bytes) at once, then processing it rune-by-rune (not byte-by-byte). To literally read the file one byte at a time (which is very likely not what you want), you must do exactly that:

f, err := os.Open("path")
if err != nil {
    panic(err)
}

b := make([]byte, 1)

for {
    err := f.Read(b)
    if err != nil && !errors.Is(err, io.EOF) {
        fmt.Println(err)
        break
    }

    // process the one byte b[0]

    if err != nil {
        // end of file
        break
    }
}

However, what you more likely want is to read the file efficiently, and process it one byte at a time. For this, you should use a buffered reader:

f, err := os.Open("path")
if err != nil {
    panic(err)
}

br := bufio.NewReader(f)

// infinite loop
for {

    b,err := br.ReadByte()

    if err != nil && !errors.Is(err, io.EOF) {
        fmt.Println(err)
        break
    }

    // process the one byte b

    if err != nil {
        // end of file
        break
    }
}
Adrian
  • 42,911
  • 6
  • 107
  • 99
  • 1
    This for-loop is not working: expected boolean or range expression, found assignment (missing parentheses around composite literal?) – h0ch5tr4355 Apr 19 '22 at 13:26
  • `for b, err := binFileReader.ReadByte(); err == nil; { fmt.Println(b) }` Something like this is needed I think – h0ch5tr4355 Apr 19 '22 at 13:33