如何在从文件中读取时找到EOF

huangapple go评论88阅读模式
英文:

How to find EOF while reading from a file

问题

我正在使用以下代码在Go中读取文件:

spoon, err := ioutil.ReadFile(os.Args[1])
if err != nil {
    panic("文件读取错误")
}

现在,我检查我选择的每个字节是什么字符。例如:

spoon[i] == ' ' //用于检查空格

同样,我读取整个文件(我知道可能有其他读取文件的方法),但保持这种方式不变,我如何知道我已经到达文件的结尾(EOF),并且应该停止进一步读取?

请不要建议找到spoon的长度并开始循环。我想要一种确定的方法来找到EOF。

英文:

I am using the following code to read a file in Go:

spoon , err := ioutil.ReadFile(os.Args[1])
if err!=nil {
        panic ("File reading error")
}

Now I check for every byte I pick for what character it is. For example:

spoon[i]==' ' //for checking space

Likewise I read the whole file (I know there maybe other ways of reading it)
but keeping this way intact, how can I know that I have reached EOF of the file and I should stop reading it further?

Please don't suggest to find the length of spoon and start a loop. I want a sure shot way of finding EOF.

答案1

得分: 30

使用io.EOF来测试文件结尾。例如,要计算文件中的空格数:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	if len(os.Args) <= 1 {
		fmt.Println("缺少文件名参数")
		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)
}
英文:

Use io.EOF to test for end-of-file. For example, to count spaces in a file:

package main

import (
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;os&quot;
)

func main() {
	if len(os.Args) &lt;= 1 {
		fmt.Println(&quot;Missing file name argument&quot;)
		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 == &#39; &#39; {
				spaces++
			}
		}
	}
	fmt.Println(spaces)
}

答案2

得分: 9

这是你需要查找以了解有关文件结束(EOF)的信息的部分:

if err != nil {
		if errors.Is(err, io.EOF) { // GoLang文档中的首选方式
			fmt.Println("读取文件完成...")
		}
		break
	}
英文:

This is what you need to look for to find out about End Of File(EOF)

if err != nil {
		if errors.Is(err, io.EOF) { // prefered way by GoLang doc
			fmt.Println(&quot;Reading file finished...&quot;)
		}
		break
	}

答案3

得分: 8

ioutil.ReadFile()将整个文件的内容读入一个字节切片中。你不需要担心EOF(文件结束符)。EOF是在你一次读取一个块时需要的一个构造。当你一次读取一个块时,你需要知道哪个块已经到达了文件的末尾。

ioutil.ReadFile()返回的字节切片的长度就是你所需要的。

data := ioutil.ReadFile(os.Args[1])

// 我们需要知道数据的大小吗?
slice_size := len(data)

// 我们需要查看每个字节吗?
for _,byte := range data {
    // 对每个字节做一些操作
}
英文:

ioutil.ReadFile() reads the entire contents of the file into a byte slice. You don't need to be concerned with EOF. EOF is a construct that is needed when you read a file one chunk at a time. You need to know which chunk has reached the end of the file when you're reading one chunk at a time.

The length of the byte slice returned by ioutil.ReadFile() is all you need.

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
}

答案4

得分: 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没有返回错误)。

英文:

When you use ioutil.ReadFile(), you don't ever see io.EOF, by design, because ReadFile will read the whole file until EOF is reached. So the slice it returns is the whole file. From the doc:

> ReadFile reads the file named by filename and returns the contents. A successful call returns err == nil, not err == EOF. Because ReadFile reads the whole file, it does not treat an EOF from Read as an error to be reported.

From your question, you explicitly mention that you are aware there are other ways to read the file, and some of those ways require you to test the error for io.EOF, but not ReadFile.

Then, with the slice you have, you can read the file using the for...range construct, as others have mentioned. This is a sure way to read the whole file and nothing more (again, ReadFile takes care of that). Or iterating from 0 to len(spoon) - 1 would work too, but range is more idiomatic and basically does the same.

In other words: when you reach the end of the slice, you reach the end of the file (provided ReadFile did not return an error).

答案5

得分: 2

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

for i, b := range spoon {
        // 在索引'i'处是字节'b'
        // 在文件的偏移量'i'处,读取了'b'
        ... 在这里做一些有用的事情
}
英文:

A slice has no concept of end of file. The slice returned by ioutil.ReadFile has a specific length, which reflects the size of the file it was read from. A common idiom, but only one of the possible used in this case, is to range the slice, effectively "consuming" all of the bytes, originally sitting in the file:

for i, b := range spoon {
        // At index &#39;i&#39; is byte &#39;b&#39;
        // At file&#39;s offset &#39;i&#39;, &#39;b&#39; was read
        ... do something useful here
}

huangapple
  • 本文由 发表于 2013年1月23日 06:49:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/14469511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定