web-dev-qa-db-ja.com

Golang、ファイルポインターを巻き戻す適切な方法

_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)
        }

    }
}
_

ここでは2つのリーダーを使用してcsvファイルから読み取ります。ファイルを巻き戻すには、data.Seek(0, 0)を使用します。これは良い方法ですか?または、2番目の読み取りの前に、ファイルを閉じて再度開くことをお勧めします。

_*File_を_io.Reader_として使用することも正しいですか?または、r := ioutil.NewReader(data)を実行することをお勧めします

14
Shadowfax

ファイルの先頭を探すのは、提案したとおりに File.Seek(0, 0) (または定数:File.Seek(0, io.SeekStart)を使用する方が安全です)を使用するのが最も簡単ですが、忘れないでください。 :

O_APPENDで開かれたファイルに対するSeekの動作は指定されていません。

(ただし、これはあなたの例には適用されません。)

ポインターをファイルの先頭に設定すると、ファイルを閉じて再度開くよりも常に高速です。ファイルの異なる「小さな」部分を何度も回交互に読み取る必要がある場合は、maybeシークの繰り返しを避けるために、ファイルを2回開くことが有益な場合があります(パフォーマンスの問題がある場合にのみ、これを心配してください)。

また、 *os.Fileio.Reader を実装しているため、io.Readerとして使用できます。質問でioutil.NewReader(data)とは何ですか?(パッケージ io/ioutil にはそのような機能はありません。おそらく bufio.NewReader() ?)ですが、ファイルから読み取る必要はありません。

17
icza