英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论