Golang,重新定位文件指针的正确方法

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

Golang, a proper way to rewind file pointer

问题

package main

import (
	"bufio"
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"os"
)

func main() {
	data, err := os.Open("cc.csv")
	defer data.Close()
	if err != nil {
		log.Fatal(err)
	}

	s := bufio.NewScanner(data)
	for s.Scan() {
		fmt.Println(s.Text())
		if err := s.Err(); err != nil {
			panic(err)
		}
	}
	// 这样做是正确的吗?
	data.Seek(0, 0)
	r := csv.NewReader(data)

	for {
		if record, err := r.Read(); err == io.EOF {

			break
		} else if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println(record)
		}

	}
}

我在这里使用了两个读取器来读取一个 csv 文件
使用 `data.Seek(0, 0)` 来倒回文件是一个好的方式吗还是在第二次读取之前关闭文件并重新打开更好

使用 `*File` 作为 `io.Reader` 是正确的吗还是使用 `r := ioutil.NewReader(data)` 更好
英文:
package main

import (
	"bufio"
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"os"
)

func main() {
	data, err := os.Open("cc.csv")
	defer data.Close()
	if err != nil {
		log.Fatal(err)
	}

	s := bufio.NewScanner(data)
	for s.Scan() {
		fmt.Println(s.Text())
		if err := s.Err(); err != nil {
			panic(err)
		}
	}
	// Is it a proper way?
	data.Seek(0, 0)
	r := csv.NewReader(data)

	for {
		if record, err := r.Read(); err == io.EOF {

			break
		} else if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println(record)
		}

	}
}

I use two readers here to read from a csv file.
To rewind a file I use data.Seek(0, 0) is it a good way? Or it's better to close the file and open again before second reading.

Is it also correct to use *File as an io.Reader ? Or it's better to do r := ioutil.NewReader(data)

答案1

得分: 29

将文件指针定位到文件开头最简单的方法是使用File.Seek(0, 0)(或更安全地使用常量:File.Seek(0, io.SeekStart)),就像你建议的那样。但是不要忘记:

> 使用O_APPEND打开的文件的Seek行为未指定。

(不过这不适用于你的示例。)

将指针设置到文件开头总是比关闭和重新打开文件要快得多。如果你需要多次读取文件的不同的“小”部分,并且交替进行,那么也许打开文件两次以避免重复寻找可能是有利的(只有在性能问题时才需要考虑这个)。

而且,*os.File实现了io.Reader,所以你可以将其作为io.Reader使用。我不知道你在问题中提到的ioutil.NewReader(data)是什么(io/ioutil包中没有这样的函数;也许你是指bufio.NewReader()?),但肯定不需要它来从文件中读取。

英文:

Seeking to the beginning of the file is easiest done using File.Seek(0, 0) (or more safely using a constant: File.Seek(0, io.SeekStart)) just as you suggested, but don't forget that:

> The behavior of Seek on a file opened with O_APPEND is not specified.

(This does not apply to your example though.)

Setting the pointer to the beginning of the file is always much faster than closing and reopening the file. If you need to read different, "small" parts of the file many times, alternating, then maybe it might be profitable to open the file twice to avoid repeated seeking (worry about this only if you have peformance problems).

And again, *os.File implements io.Reader, so you can use it as an io.Reader. I don't know what ioutil.NewReader(data) is you mentioned in your question (package io/ioutil has no such function; maybe you meant bufio.NewReader()?), but certainly it is not needed to read from a file.

huangapple
  • 本文由 发表于 2017年2月15日 17:21:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/42245227.html
匿名

发表评论

匿名网友

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

确定