4

現在、ファイルを1行ずつ読み取るこのコードがあります(\ 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 ループで 2 回書くことに慣れていませんbuf.ReadString("\n")。改善のための提案はありますか?

4

2 に答える 2

4

bufio.ReadStringは、入力で delim が最初に出現するまで読み取り、区切り文字までのデータを含む文字列を返します。区切り文字を見つける前に ReadString でエラーが発生した場合、エラーの前に読み取られたデータとエラー自体 (多くの場合 io.EOF) が返されます。ReadString は、返されたデータが delim で終わっていない場合にのみ、err != nil を返します。

buf.ReadString('\n')以外のエラーが返された場合io.EOF、たとえばbufio.ErrBufferFull、無限ループに陥ります。また、ファイルが で終わらない場合'\n'、最後の'\n'.

buf.ReadString('\n')これは、 1 回実行される、より堅牢なソリューションです。

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"))
    }
}
于 2012-10-11T00:40:08.497 に答える
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)
    }
}

エラーは 1 点で発生するため、エラー処理が簡素化されます。ピーターが提案したように、最後の行から改行を削除すると、最後の改行がある場合とない場合があるファイルが可能になります。最近のほとんどのテキスト ファイルは、利用可能なメモリに比べて非常に小さいため、これらを一気に読むことが適切です。

于 2012-10-11T13:46:57.723 に答える