我目前有这段代码将逐行读取文件(由\ n分隔)
file, _ := os.Open(filename) //deal with the error later
defer file.Close()
buf := bufio.NewReader(file)
for line, err := buf.ReadString('\n'); err != io.EOF; line, err = buf.ReadString('\n')
{
fmt.Println(strings.TrimRight(line, "\n"))
}
但是,我觉得在for循环中两次写buf.ReadString("\n")
感觉不舒服,有没有人有任何改进建议?
答案 0 :(得分:3)
bufio.ReadString读取,直到输入中第一次出现delim, 返回包含数据的字符串,包括 分隔符。如果ReadString在找到之前遇到错误 分隔符,它返回错误和错误之前读取的数据 本身(通常是io.EOF)。 ReadString返回err!= nil当且仅当 返回的数据不会以delim结尾。
如果buf.ReadString('\n')
返回io.EOF
以外的错误,例如bufio.ErrBufferFull
,则您将处于无限循环中。此外,如果文件未以'\n'
结尾,则您会在最后'\n'
之后静默忽略数据。
这是一个更强大的解决方案,只执行一次buf.ReadString('\n')
。
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
func main() {
filename := "FileName"
file, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
buf := bufio.NewReader(file)
for {
line, err := buf.ReadString('\n')
if err != nil {
if err != io.EOF || len(line) > 0 {
fmt.Println(err)
return
}
break
}
fmt.Println(strings.TrimRight(line, "\n"))
}
}
答案 1 :(得分:1)
大多数逐行读取的代码可以通过不逐行读取来改进。如果您的目标是阅读文件并访问这些行,那么以下内容几乎总是更好。
package main
import (
"fmt"
"io/ioutil"
"log"
"strings"
)
func main() {
b, err := ioutil.ReadFile("filename")
if err != nil {
log.Fatal(err)
}
s := string(b) // convert []byte to string
s = strings.TrimRight(s, "\n") // strip \n on last line
ss := strings.Split(s, "\n") // split to []string
for _, s := range ss {
fmt.Println(s)
}
}
任何错误都会在一个点上出现,因此简化了错误处理。正如彼得所建议的那样,从最后一行剥离换行允许可能有也可能没有最终换行符的文件。
表示,与现有内存相比,大多数文本文件都很小,所以一次读取这些内容是合适的。