[英]How to test EOF on io.Reader in Go?
Go的io.Reader
文檔聲明Read()
可以同時返回非零n
值和io.EOF
。 不幸的是, File
的Read()
方法不會這樣做。
當達到EOF並且仍然可以讀取一些字節時,文件的Read方法返回非零n
和nil
錯誤。 只有當我們嘗試讀取已經在文件末尾的時候才會返回零n
和io.EOF
作為錯誤。
我找不到一個簡單的方法來測試是否到達EOF而不嘗試從文件中讀取數據。 如果我們使用0字節的緩沖區執行Read(),我們會返回零n
和nil
錯誤,盡管我們位於文件的末尾。
為避免最后一次讀取,我發現的唯一解決方案是跟蹤自己在文件中讀取的剩余字節數。 有更簡單的解決方案嗎?
您可以創建一個新類型,跟蹤到目前為止讀取的字節數。 然后,在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>
代碼為要點 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.