使用bufio.reader从go中的文本文件中读取行

时间:2015-04-26 19:01:38

标签: go

for {
    v, err = nextNum(reader, ' ')
    if err != nil {
        break
    }
    w, err = nextNum(reader, ' ')
    if err != nil {
        break
    }
    cost, err = nextNum(reader, '\n')
    if err != nil {
        break
    }
    fmt.Println(v, w, cost)
}

我的文本文件由三个coloumns和n行组成。第一次调用nextNum时第一行中的数字和第一列将被返回,下一次是第二列和第一行中的数字,依此类推。我的问题是当我到达终点并且我最后一次调用nextNum然后我将收到一个EOF错误并且最后一行将永远不会打印出来,因为之前会调用break。有关如何解决问题的任何建议吗?

干杯

2 个答案:

答案 0 :(得分:1)

我猜您文件的最后一行没有新行,而只是以EOF结尾。这是他的正确吗?因此,最后一列未正确解析,因为它不以预期字符(\n)结束。

您没有准确地向我们展示您使用bufio.Reader的确切方式,但无论哪种方式,您都需要考虑文件末尾缺少的新行(无论是将其视为错误还是不)。使用bufio.Reader.ReadString\n分隔符等方法不会自动将EOF视为行尾,但会返回有效内容和EOF(即您可以在同一个调用中同时获取数据和错误 - 请注意,这与bufio.Reader.Read)中的行为不同。

说到这一点,使用csv包可能对您有利。它将解决EOF问题,您还可以从意外数量的列上获得一些更好的错误消息。评论或引用等附加功能可能对您的目的有利或不利。

Example:

// No line break at the end, pure EOF (still works)
data := "one 1\ntwo 2\nthree 3\nfour 4"

// You can wrap your file reader with bufio.Reader here
cr := csv.NewReader(bytes.NewReader([]byte(data)))
cr.Comma = ' '
cr.FieldsPerRecord = 2

var err error
for err == nil {
    var columns []string
    if columns, err = cr.Read(); err == nil {
        fmt.Println(columns)
        // err = processRow(columns)
    }
}
if err != io.EOF {
    // Parse error
    panic(err)
}   

答案 1 :(得分:0)

来自bufio docs

  

在EOF,计数将为零,错误将为io.EOF

所以你可以简单地测试一下。比如将if err != nil更改为if err != nil && err != io.EOF

if err == io.EOF {
    fmt.Println(v, w, cost)
    break
}
if err != nil {
    break
}
fmt.Println(v, w, cost)

虽然你真的应该对错误做点什么而不是忽略它。