これまでに読み込んだバイト数を記録する新しいタイプを作成することができます。次に、EOFチェック時に、読み取られた予想バイト数と実際に読み取られたバイト数を比較できます。ここにサンプル実装があります。
:あなたはeofReaderに任意のリーダーをラップすることによって、このタイプを使用することができます
package main
// ... imports
// eofReader can be checked for EOF, without a Read.
type eofReader struct {
r io.Reader
count uint64
}
// AtEOF returns true, if the number of bytes read equals the file size.
func (r *eofReader) AtEOF() (bool, error) {
f, ok := r.r.(*os.File)
if !ok {
return false, nil
}
fi, err := f.Stat()
if err != nil {
return false, err
}
return r.Count() == uint64(fi.Size()), nil
}
// Read reads and counts.
func (r *eofReader) Read(buf []byte) (int, error) {
n, err := r.r.Read(buf)
atomic.AddUint64(&r.count, uint64(n))
return n, err
}
// Count returns the count.
func (r *eofReader) Count() uint64 {
return atomic.LoadUint64(&r.count)
}
:eofReader
が読み込まれたバイト数を追跡した場合に、ファイルのサイズと比較する基本的なタイプはファイルであります
func main() {
f, err := os.Open("main.go")
if err != nil {
log.Fatal(err)
}
r := &eofReader{r: f}
log.Println(r.AtEOF())
if _, err = ioutil.ReadAll(r); err != nil {
log.Fatal(err)
}
log.Println(r.AtEOF())
}
// 2016/12/19 03:49:35 false <nil>
// 2016/12/19 03:49:35 true <nil>
コードgist。
AFAIKではありません。シークや何かを使って現在のポジションを得ることができますが、それはより多くのシステムコールを必要とするので遅くなります。 –
_always_がいくつかのバイトを読み込み、EOFを返す型を作るのはなぜですか? – JimB
@JimBそれはすごいトリックです。私はその解決方法を採用します。しかし、先読みの代わりに、私はio.EOFをちょうど時間内に返すことができるように、読み込む残りのバイトを追跡します。私が最も好きなのは、自分のプログラムのどこにでもコードを変更する必要がないからです。私は、ファイルへのラッパーを提供する必要があります。 2つのオプションで素敵な答えを書いたら、私はそれをあなたに与えます。 – chmike