2012-10-10 34 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) 
    } 
} 

任何錯誤都在一個點上給你,所以錯誤處理被簡化了。正如彼得所建議的那樣,從最後一行剝離換行符允許可能包含或不包含最終換行符的文件。現在大多數文本文件與可用內存相比都很小,因此閱讀這些文件是合適的。