簡體   English   中英

如何在Go中的io.Reader上測試EOF?

[英]How to test EOF on io.Reader in Go?

Go的io.Reader文檔聲明Read()可以同時返回非零n值和io.EOF 不幸的是, FileRead()方法不會這樣做。

當達到EOF並且仍然可以讀取一些字節時,文件的Read方法返回非零nnil錯誤。 只有當我們嘗試讀取已經在文件末尾的時候才會返回零nio.EOF作為錯誤。

我找不到一個簡單的方法來測試是否到達EOF而不嘗試從文件中讀取數據。 如果我們使用0字節的緩沖區執行Read(),我們會返回零nnil錯誤,盡管我們位於文件的末尾。

為避免最后一次讀取,我發現的唯一解決方案是跟蹤自己在文件中讀取的剩余字節數。 有更簡單的解決方案嗎?

您可以創建一個新類型,跟蹤到目前為止讀取的字節數。 然后,在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM