从文件读取时如何找到EOF
Posted
技术标签:
【中文标题】从文件读取时如何找到EOF【英文标题】:How to find EOF while reading from a file 【发布时间】:2013-01-06 07:55:14 【问题描述】:我正在使用以下代码在 Go 中读取文件:
spoon , err := ioutil.ReadFile(os.Args[1])
if err!=nil
panic ("File reading error")
现在我检查我选择的每个字节是什么字符。例如:
spoon[i]==' ' //for checking space
同样,我阅读了整个文件(我知道可能还有其他阅读方式) 但是保持这种方式不变,我怎么知道我已经达到了文件的 EOF 并且我应该停止进一步阅读它?
请不要建议找到spoon
的长度并开始循环。我想要找到 EOF 的可靠方法。
【问题讨论】:
简单的解决方案:单片眼镜! @thang 什么是单片眼镜? @Worlock:再一次,上面显示的问题不直接涉及任何EOF。它可能仅从返回的spoon
切片中的字节数推断出来,如果按顺序读取文件,则会出现io.EOF
。即使io.ReadFile
可能从未在此设置中看到任何 EOF。 stat
文件,调整缓冲区(返回的切片)并要求操作系统完全填充它会更便宜。
【参考方案1】:
使用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)
【讨论】:
Read 可以在 EOF 旁边返回数据:“调用方应始终处理返回的 n > 0 字节,然后再考虑错误错误。这样做可以正确处理读取某些字节后发生的 I/O 错误,以及两者允许的 EOF 行为。”【参考方案2】: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
【讨论】:
您写道“您需要知道哪个块已到达文件末尾”。我怎么知道?顺便说一句你写的?还是总结不同?【参考方案3】:这是您需要查找的有关文件结尾(EOF)的信息
if err != nil
if errors.Is(err, io.EOF) // prefered way by GoLang doc
fmt.Println("Reading file finished...")
break
【讨论】:
【参考方案4】:当您使用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 没有返回错误)。
【讨论】:
【参考方案5】:切片没有文件结尾的概念。 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
【讨论】:
以上是关于从文件读取时如何找到EOF的主要内容,如果未能解决你的问题,请参考以下文章
C语言从TXT文档中读取一组数字时如何判断已经读到最后一个数字?