22

次のコードを使用して、Go でファイルを読み取ります。

spoon , err := ioutil.ReadFile(os.Args[1])
if err!=nil {
        panic ("File reading error")
}

今、私はそれがどの文字であるかを選択するすべてのバイトをチェックします。例えば:

spoon[i]==' ' //for checking space

同様に、ファイル全体を読み取ります(他の方法で読み取ることもできます)が、この方法をそのままにしておくと、ファイルのEOFに達したことをどうやって知ることができ、それ以上読み取るのをやめるべきですか?

spoonの長さを見つけてループを開始することを提案しないでください。EOFを確実に見つける方法が欲しいです。

4

5 に答える 5

29

io.EOFファイルの終わりをテストするために使用します。たとえば、ファイル内のスペースをカウントするには、次のようにします。

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    if len(os.Args) <= 1 {
        fmt.Println("Missing file name argument")
        return
    }
    f, err := os.Open(os.Args[1])
    if err != nil {
        fmt.Println(err)
        return
    }
    defer f.Close()
    data := make([]byte, 100)
    spaces := 0
    for {
        data = data[:cap(data)]
        n, err := f.Read(data)
        if err != nil {
            if err == io.EOF {
                break
            }
            fmt.Println(err)
            return
        }
        data = data[:n]
        for _, b := range data {
            if b == ' ' {
                spaces++
            }
        }
    }
    fmt.Println(spaces)
}
于 2013-01-22T23:44:12.750 に答える
8

ioutil.ReadFile()ファイルの内容全体をバイトスライスに読み込みます。EOF を気にする必要はありません。EOF は、一度に 1 つのチャンクでファイルを読み取るときに必要な構造です。一度に 1 つのチャンクを読み取る場合、どのチャンクがファイルの最後に到達したかを知る必要があります。

によって返されるバイト スライスの長さだけで十分ioutil.ReadFile()です。

data := ioutil.ReadFile(os.Args[1])

// Do we need to know the data size?
slice_size := len(data)

// Do we need to look at each byte?
for _,byte := range data {
    // do something with each byte
}
于 2013-01-22T22:57:02.153 に答える
3

を使用する場合ioutil.ReadFile()、設計上、io.EOF が表示されることはありません。これは、ReadFile が EOF に達するまでファイル全体を読み取るためです。したがって、返されるスライスファイル全体です。ドキュメントから:

ReadFile は、filename で指定されたファイルを読み取り、内容を返します。呼び出しが成功すると、err == EOF ではなく、err == nil が返されます。ReadFile はファイル全体を読み取るため、Read からの EOF を報告するエラーとして扱いません。

あなたの質問から、ファイルを読み取る他の方法があることを認識していることを明示的に述べています。それらの方法のいくつかは、io.EOF のエラーをテストする必要がありますが、ReadFile は必要ありません。

次に、あなたが持っているスライスを使用して、他の人が述べたように、 for...range コンストラクトを使用してファイルを読み取ることができます。これは、ファイル全体を読み取る確実な方法であり、それ以上のものではありません (これも ReadFile が処理します)。または、 0 から len(spoon) - 1 まで反復しても機能しますが、範囲はより慣用的であり、基本的に同じことを行います。

つまり、スライスの最後に到達すると、ファイルの最後に到達します(ReadFile がエラーを返さなかった場合)。

于 2013-01-23T13:30:38.047 に答える
2

スライスには、ファイルの終わりの概念がありません。によって返されるスライスにioutil.ReadFileは、読み取り元のファイルのサイズを反映する特定の長さがあります。一般的なイディオムですが、この場合に使用できるのは 1 つだけですが、スライスの範囲を指定して、ファイル内にもともと存在するすべてのバイトを効果的に「消費」することです。

for i, b := range spoon {
        // At index 'i' is byte 'b'
        // At file's offset 'i', 'b' was read
        ... do something useful here
}
于 2013-01-22T22:56:10.470 に答える