Help us understand the problem. What is going on with this article?

Go でファイルを1行ずつ読み込む(csv ファイルも)

More than 3 years have passed since last update.

概要

ファイルを読み込んで処理することがよくあるので忘備用のメモです.

ファイルを1行ずつ読み込む

bufio.Readerで読み込む

ReadString

引数にファイルが指定されていれば,ファイルをオープンして1行ずつ読み込みます.
引数が指定されていなければ,標準入力から1行ずつ読み込みます.

追記:ReadString('\n')で読み込むとWindowsの場合\rが残ってしまうのでReadLineの方がいいとのコメントいただきましたので,ReadLine使った版も載せておきました.

os.EOFでなくてio.EOFなのがはまりどころでした.

Readerはファイルをクローズすれば閉じられるみたいです.

package main

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

func main() {
        var fp *os.File
        var err error

        if len(os.Args) < 2 {
                fp = os.Stdin
        } else {
                fmt.Printf(">> read file: %s\n", os.Args[1])
                fp, err = os.Open(os.Args[1])
                if err != nil {
                        panic(err)
                }
                defer fp.Close()
        }

        reader := bufio.NewReaderSize(fp, 4096)
        for line := ""; err == nil; line, err = reader.ReadString('\n') {
                fmt.Print(line)
        }
        if err != io.EOF {
                panic(err)
        }
}

ReadLine

コメントいただいたので修正版.

package main

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

func main() {
        var fp *os.File
        var err error

        if len(os.Args) < 2 {
                fp = os.Stdin
        } else {
                fmt.Printf(">> read file: %s\n", os.Args[1])
                fp, err = os.Open(os.Args[1])
                if err != nil {
                        panic(err)
                }
                defer fp.Close()
        }

        reader := bufio.NewReaderSize(fp, 4096)
        for {
                line, _, err := reader.ReadLine()
                fmt.Println(string(line))
                if err == io.EOF {
                        break
                } else if err != nil {
                        panic(err)
                }
        }
}

bufio.Scannerで読み込む (推奨)

面倒だなとおもったらbufioにScanner という便利なものがありました.
http://golang.org/pkg/bufio/#example_Scanner_lines
サンプルを参考に,上の例と同じにするとこんな感じでしょうか.

package main

import (
        "bufio"
        "fmt"
        "os"
)

func main() {
        var fp *os.File
        var err error

        if len(os.Args) < 2 {
                fp  = os.Stdin
        } else {
                fp, err = os.Open(os.Args[1])
                if err != nil {
                   panic(err)
                }
                defer fp.Close()
        }

        scanner := bufio.NewScanner(fp)
        for scanner.Scan() {
            fmt.Println(scanner.Text())
        }
        if err := scanner.Err(); err != nil {
            panic(err)
        }
}

csv(tsv)形式のファイルの読み込み

csv形式のファイルを読み込むReaderが用意されているのでこれを使えば簡単.
区切り文字の指定をReader.Commaに設定するのがなんか気持ち悪いですが・・・.
下記はタブ区切りのファイルを読む場合のサンプルです.

package main

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

func main() {

        var fp *os.File
        if len(os.Args) < 2 {
                fp = os.Stdin
        } else {
                var err error
                fp, err = os.Open(os.Args[1])
                if err != nil {
                        panic(err)
                }
                defer fp.Close()
        }

        reader := csv.NewReader(fp)
        reader.Comma = '\t'
        reader.LazyQuotes = true // ダブルクオートを厳密にチェックしない!
        for {
                record, err := reader.Read()
                if err == io.EOF {
                        break
                } else if err != nil {
                        panic(err)
                }
                fmt.Println(record)
        }
}
ikawaha
形式言語理論・オートマトン / 正規表現エンジン,キーワードフィルタ,係り受け解析,固有表現抽出 / 押してだめならふて寝しろ
http://ikawaha.hateblo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした