Home > Article > Backend Development > Idiom Go to read exactly N lines (instead of one byte) of text?
php editor Apple will introduce you to an idiom Go that accurately reads a specified number of lines (rather than one byte) of text. When working with text files, we often need to read a specific number of lines, rather than reading byte by byte. Using the bufio package of the Go language, we can easily achieve this goal. Next, we will detail how to use this idiom to achieve the function of accurately reading a specified number of lines of text. Let’s explore together!
I have a CSV from the report generator that has some non-CSV preamble added, for example:
Time Off Requests My Org Street Address City, State ZIP Col1,Col2,Col3 r1c1,r1c2,r1c3 r2c1,r2c2,r2c3
I need to discard these 6 lines before passing the file's io.Reader to csv.NewReader and trying ReadAll(), so I need to make sure I don't read any bytes after line 6.
I originally thought of bufio.Scanner and calling Scan() 6 times in a loop, but then realized through experimentation that the "buf" in bufio means I have no control over where the buffered read ends, and it might read Past the real start position CSV.
So I figured out a way, which is to read byte by byte until I count 6 newlines (10):
f, _ := os.Open(csvPath) // Read just past report-generated 6-line preamble b := make([]byte, 1) for i := 0; i < 6; { f.Read(b) if b[0] == 10 { i++ } } r := csv.NewReader(f) records, err = r.ReadAll() ...
This works. But is there a more idiomatic Go way?
You don't need to avoid using bufio
, in fact you should choose to use buffered IO whenever possible. What you can't do is use the original reader after accessing it via bufio.Reader
, i.e. don't pass os.File
after using bufio.NewReader
To csv.NewReader
, continue using bufio.Reader
which may contain data that has been read from the file.
Once you have bufio.Reader
, you can use all methods to read parts of the stream without worrying about reading byte by byte.
buf := bufio.NewReader(f) // the preambled is defined as 6 lines for i := 0; i < 6; i++ { line, err := buf.ReadBytes('\n') if err != nil { log.Fatal(err) } fmt.Printf("line: %q\n", line) } r := csv.NewReader(buf) records, err := r.ReadAll() if err != nil { log.Fatal(err) } fmt.Printf("records: %q\n", records)
The above is the detailed content of Idiom Go to read exactly N lines (instead of one byte) of text?. For more information, please follow other related articles on the PHP Chinese website!