2012-10-10 31 views
3

我现在有这一段代码,将读取线(由\ 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")) 
} 

不过我不觉得舒服写buf.ReadString("\n")两次在for循环中,有没有人有任何改进建议?

回答

3

bufio.ReadString读取直到DELIM的输入,返回 含有至多并包括 定界符数据的字符串的第一次出现。如果ReadString在发现 定界符之前遇到错误,它将返回错误前读取的数据和错误 本身(通常为io.EOF)。 ReadString返回err!= nil当且仅当 返回的数据不以delim结尾。

如果buf.ReadString('\n')返回例如bufio.ErrBufferFullio.EOF其他错误,你将在一个无限循环。另外,如果文件没有以'\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")) 
    } 
} 
+0

非常感谢,非常好的答案! – djhworld

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

任何错误都在一个点上给你,所以错误处理被简化了。正如彼得所建议的那样,从最后一行剥离换行符允许可能包含或不包含最终换行符的文件。现在大多数文本文件与可用内存相比都很小,因此阅读这些文件是合适的。