Idiom Go to read exactly N lines (instead of one byte) of text?

WBOY
Release: 2024-02-09 08:40:09
forward
959 people have browsed it

惯用语 Go 精确读取 N 行(而不是一个字节)的文本?

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!

Question content

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
Copy after login

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()
...
Copy after login

This works. But is there a more idiomatic Go way?

Workaround

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)
Copy after login

Complete example

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!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!