隐藏的巨坑-- golang按行读文件中的bug

橙子1001 2017-10-24 10:13:54
如果我们要用golang按行读取一个文件,通过会搜索一下吧, 网上给出的答案大多都是这样的:

f, err := os.Open("test.txt")
if err != nil {
panic(err)
}
defer f.Close()

rd := bufio.NewReader(f)
for {
line, err := rd.ReadString('\n') //以'\n'为结束符读入一行

if err != nil || io.EOF == err {
break
}
fmt.Println(line)
}



表面上看起来没什么问题,but.. 你有没有遇到这种文件:
[root@ccc conf]# svn diff
Index: ves.mapping
===================================================================
--- ves.mapping (revision 941)
+++ ves.mapping (working copy)
@@ -26,4 +26,4 @@
scripts/modules/accountManage/systemAccountListPage.js#00b534
scripts/modules/accountManage/appAccountListPage.js#b1d84031
scripts/modules/operationManage/mod_measured-settings.js#25
-scripts/modules/operationManage/system-manage.js#5201c65e9
\ No newline at end of file

用svn diff 命令可以看到 No newline at end of file
用上面这段程序读这种文件的时候 ,会导致最后一行没打印出来,因为err==io.EOF, 但实际上这时候line是有值的


解决办法 :


f, err := os.Open("test.txt")
if err != nil {
panic(err)
}
defer f.Close()

rd := bufio.NewReader(f)
for {
line, err := rd.ReadString('\n') //以'\n'为结束符读入一行

if err != nil || io.EOF == err {
if line==""{
break
}
}
fmt.Println(line)
}



或者:


f, err := os.Open("test.txt")
if err != nil {
panic(err)
}
defer f.Close()

rd := bufio.NewReader(f)
for {
line, err := rd.ReadString('\n') //以'\n'为结束符读入一行
fmt.Println(line)
if err != nil || io.EOF == err {
break
}
}





...全文
3238 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_16055183 2019-07-25
  • 打赏
  • 举报
回复
我也遇到跟你一样的问题。我还有个问题,ReadString('\n')不是读取一行吗,为什么用for循环会逐行读取文件,而不是反复读取第一行
tq1086 2018-11-09
  • 打赏
  • 举报
回复
这是文档里的一段

If ReadBytes encounters an error before finding a delimiter, it returns the data read before the error and the error itself (often io.EOF).

不过是在ReadBytes函数里说明的,所以应该是一个文档的bug :-)

来源:https://golang.google.cn/pkg/bufio/#Reader.ReadBytes
哈哈gogo 2018-09-28
  • 打赏
  • 举报
回复
这是你的bug
「已注销」 2018-09-18
  • 打赏
  • 举报
回复
设计再好的语言也经不住你们这样报bug
xinyu391 2018-02-08
  • 打赏
  • 举报
回复
这是你没有看懂ReadString()的函数说明 人家明明说了,及时出错,err!=nil,也会把已经读到的数据返回出来的。
smmssmms 2017-12-27
  • 打赏
  • 举报
回复
这里的io.EOF代表着文件结束标志。在go里面经常有这样的惯用写法: if err != nil && err != io.EOF { return err }
fibbery 2017-11-06
  • 打赏
  • 举报
回复
这个不算bug,是一种行为。

2,190

社区成员

发帖
与我相关
我的任务
社区描述
go语言学习与交流版
社区管理员
  • go语言社区
  • Freeman Z
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧