卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34597本站已运行393

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

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

php小编苹果将为大家介绍一种精确读取指定行数(而不是一个字节)的文本的惯用语Go。在处理文本文件时,我们经常需要读取特定行数的内容,而不是逐个字节读取。使用Go语言的bufio包,我们可以轻松实现这个目标。接下来,我们将详细介绍如何使用这个惯用语来实现精确读取指定行数的文本的功能。让我们一起来探索吧!

问题内容

我有一个来自报告生成器的 CSV,它添加了一些非 CSV 前导码,例如:

Time Off Requests

My Org
Street Address
City, State  ZIP

Col1,Col2,Col3
r1c1,r1c2,r1c3
r2c1,r2c2,r2c3

在将文件的 io.Reader 传递给 csv.NewReader 并尝试 ReadAll() 之前,我需要丢弃这 6 行,因此我需要确保我不会读取第 6 行之后的任何一个字节。

我最初想到 bufio.Scanner 并在循环中调用 Scan() 6 次,但后来通过实验意识到 bufio 中的“buf”意味着我无法控制缓冲读取的结束位置,并且它可能会读取超过真正开始的位置CSV。

所以我想出了一个办法,就是逐字节读取,直到数到 6 个换行符 (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()
...

这有效。但是,有更惯用的 Go 方式吗?

解决方法

您不需要避免使用 bufio,事实上您应该尽可能选择使用缓冲 IO。您不能做的是通过 bufio.Reader 访问它之后使用原始阅读器,即,在使用 bufio.NewReader 后,不要将 os.File 传递给 csv.NewReader,继续使用 bufio.Reader 可能包含已从文件中读取的数据。

一旦有了 bufio.Reader,您就可以使用所有方法来读取流的各个部分,而无需担心逐字节读取。

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: %qn", line)
}
r := csv.NewReader(buf)
records, err := r.ReadAll()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("records: %qn", records)

完整示例

卓越飞翔博客
上一篇: 如何使用 Gin 在 HTTP 服务器中即时生成 zip / 7z 存档?
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏