英文:
Read lines from text file in go, with bufio.reader
问题
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)
}
我的文本文件由三列和n行组成。第一次调用nextNum时,将返回第一行和第一列中的数字,下一次将返回第二列和第一行中的数字,依此类推。我的问题是当我到达最后一次调用nextNum时,我将收到一个EOF错误,并且最后一行将永远不会被打印出来,因为在此之前会调用break。有关如何解决这个问题的建议吗?
谢谢。
英文:
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)
}
My text file consists of three coloumns and n rows. The first time nextNum is called the number in the first row and first column will be returned, next time the number in the second column and first row, and so on. My problem is when i get to the end and i call nextNum for the last time then i will recieve an EOF error and the last line will never get printed out, becuase break will be called before. Any suggestions on how to solve the problem?
CHeers
答案1
得分: 1
我猜测你的文件中最后一行没有换行符,而是以EOF
结束。这是正确的吗?因此,最后一列没有被正确解析,因为它没有以预期的字符(\n
)结尾。
你没有向我们展示你如何使用bufio.Reader
,但无论如何,你都需要考虑文件末尾缺少换行符的情况(你可以选择将其视为错误或不处理)。使用像bufio.Reader.ReadString
这样的方法,并以\n
作为分隔符,不会自动将EOF
视为行尾,而是会返回有效的内容和EOF
(即你可以在同一次调用中获取数据和错误 - 请注意,这与bufio.Reader.Read
的行为不同)。
说到这里,你可能会发现使用csv
包更有益处。它可以解决EOF
问题,并且你还可以从一些更好的错误消息中受益,以处理意外的列数。额外的功能,如注释或引号,可能对你的目的有利或不利。
以下是一个示例:
// 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)
}
希望对你有帮助!
英文:
I guess there is no new line in the last row in your file and it's simply ending with EOF
. It his correct? As a result, the very last column is not being parsed correctly, as it doesn't end with an expected character (\n
).
You didn't show us exactly how you're using bufio.Reader
, but either way you will need to account for missing new line at the end of file (it's up to you whether treat it as an error or not). Using methods like bufio.Reader.ReadString
with \n
delimiter won't treat EOF
as the end-of-line automatically, but will return you a valid content along with EOF
(i.e. you can get both data and error at the same call – note this is a different behaviour than in bufio.Reader.Read
).
Saying this, it might be beneficial for you to use the csv
package instead. It will solve the EOF
problem and you could also benefit from some nicer error messages on unexpected number of columns. The additional features like comments or quotes might be good or bad for your purposes.
// 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)
}
答案2
得分: 0
从bufio文档中可以看到:
> 在EOF时,计数将为零,err将为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)
不过,你真的应该对错误进行处理,而不仅仅忽略它。
英文:
From the bufio docs:
> At EOF, the count will be zero and err will be io.EOF
So you can simply test for that. Like change your if err != nil
to if err != nil && err != io.EOF
or
if err == io.EOF {
fmt.Println(v, w, cost)
break
}
if err != nil {
break
}
fmt.Println(v, w, cost)
Though you really should do something with the error and not just ignore it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论