概要
ファイルを読み込んで処理することがよくあるので忘備用のメモです.
ファイルを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)
}
}