如何改进这个文件阅读代码

时间:2012-10-10 21:22:17

标签: go

我目前有这段代码将逐行读取文件(由\ 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")感觉不舒服,有没有人有任何改进建议?

2 个答案:

答案 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)
    }
}

任何错误都会在一个点上出现,因此简化了错误处理。正如彼得所建议的那样,从最后一行剥离换行允许可能有也可能没有最终换行符的文件。

表示,与现有内存相比,大多数文本文件都很小,所以一次读取这些内容是合适的。