この記事のゴール
- SJISのCSVを読み込みながら1行毎に処理を実行できるようになる
1行毎に処理したい理由
大きなCSVを処理するときに、全行読み込んでスライスにためるとメモリをたくさん使うため、1行ごとに処理を行うようにする
コード
前回の「Go言語:SJISのCSVファイルを読み込む!」でSJISのCSVを読み込む方法を説明した。そこで紹介したコードをベースに、1行ごとに逐次処理できるようにCSV読み込み処理を関数にする。
実装方法はいろいろあるが、コールバック関数を渡して、1行毎にそのコールバック関数を呼ぶような実装にした:
main.go
package main
import (
"encoding/csv"
iconv "github.com/djimenez/iconv-go"
"io"
"log"
"os"
)
func failOnError(err error) {
if err != nil {
log.Fatal("Error:", err)
}
}
func main() {
filename := "/tmp/chibashi-sjis.csv"
callbak := func(record []string) {
log.Println("ここで逐次処理")
log.Printf("%#v", record)
}
err := ReadCsv(filename, callbak)
failOnError(err)
}
func ReadCsv(filename string, callback func(record []string)) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
converter, err := iconv.NewReader(file, "sjis", "utf-8")
if err != nil {
return err
}
reader := csv.NewReader(converter)
for {
record, err := reader.Read() // 1行読み出す
if err == io.EOF {
break
} else if err != nil {
return err
}
callback(record)
}
return nil
}
実行結果
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"区", "男性人口", "女性人口"}
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"中央区", "202,213", "102,080"}
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"花見川区", "179,698", "89,369"}
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"稲毛区", "156,612", "78,199"}
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"若葉区", "151,165", "76,159"}
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"緑区", "125,956", "62,042"}
2013/12/18 19:14:56 ここで逐次処理
2013/12/18 19:14:56 []string{"美浜区", "148,951", "72,806"}