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 是一种结构,当您一次读取一个文件时需要它。当您一次读取一个块时,您需要知道哪个块已到达文件末尾。

返回的字节片的长度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 回答
5

这是您需要查找的有关文件结尾(EOF)的信息

if err != nil {
        if errors.Is(err, io.EOF) { // prefered way by GoLang doc
            fmt.Println("Reading file finished...")
        }
        break
    }
于 2021-03-05T08:33:10.730 回答
3

当您使用 时ioutil.ReadFile(),您永远不会看到 io.EOF,因为 ReadFile 将读取整个文件,直到达到 EOF。所以它返回的切片整个文件。从文档:

ReadFile 读取由 filename 命名的文件并返回内容。成功的调用返回 err == nil,而不是 err == EOF。因为 ReadFile 读取整个文件,所以它不会将 Read 中的 EOF 视为要报告的错误。

从您的问题中,您明确提到您知道还有其他方法可以读取文件,其中一些方法要求您测试 io.EOF 的错误,而不是 ReadFile。

然后,使用您拥有的切片,您可以使用 for...range 构造读取文件,正如其他人提到的那样。这是读取整个文件的可靠方法,仅此而已(再次,ReadFile 负责)。或者从 0 迭代到 len(spoon) - 1 也可以,但是 range 更惯用,基本上也是一样的。

换句话说:当您到达切片的末尾时,您就到达了文件的末尾(前提是 ReadFile 没有返回错误)。

于 2013-01-23T13:30:38.047 回答
2

切片没有文件结尾的概念。返回的切片ioutil.ReadFile具有特定的长度,它反映了读取它的文件的大小。一个常见的习惯用法,但只是在这种情况下使用的一种可能,是对切片进行范围,有效地“消耗”最初位于文件中的所有字节:

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 回答