はじめに
以下のようなCSVファイルを作成したいと思った際に、はじめうまく作成できなかったので備忘録として作成方法を残しておこうと思います。
fruit.csv
"name","color","japanese"
"apple","red","りんご"
"grape","purple","ぶどう"
"orange","orange","オレンジ"
簡単に思いつく方法
作成したいCSVのコンテンツを用意し、encoding/csv
パッケージを使用してCSVファイルを作成してみます。
package main
import (
"encoding/csv"
"os"
)
func main() {
file, err := os.Create("./fruit.csv")
if err != nil {
panic(err)
}
defer file.Close()
header := []string{"\"name\"", "\"color\"", "\"japanese\""}
records := [][]string{
{"\"apple\"", "\"red\"", "\"りんご\""},
{"\"banana\"", "\"yellow\"", "\"バナナ\""},
{"\"orange\"", "\"orange\"", "\"オレンジ\""},
}
csvWriter := csv.NewWriter(file)
csvWriter.Write(header)
csvWriter.WriteAll(records)
}
上記を実行すると以下のようになります。
fruit.csv
"""name""","""color""","""japanese"""
"""apple""","""red""","""りんご"""
"""banana""","""yellow""","""バナナ"""
"""grape""","""purple""","""ぶどう"""
"""orange""","""orange""","""オレンジ"""
ダブルクオートが各項目で3つになってしまいます。
これはencoding/csv
のWrite()
関数で"
があるとエスケープ処理が行われ、"
が追加されるためです。
具体的には、
- エスケープが必要な文字を含むフィールドと判定される→フィールドの最初と最後に
"
を追加(""apple"") -
"
をエスケープする必要があるので"
の前に"
を追加("""apple""")
という処理が行われています。
つまりencoding/csv
パッケージは"
があると前後にダブルクオートを追加し、"
の前にも"
を追加する仕様になっています。
encoding/csvに渡す値 | CSVファイルに出力される値 |
---|---|
apple | apple |
app"le | "app""le" |
"apple" | """apple""" |
解決方法
encoding/csv
パッケージを使うと難しいということがわかりました。
以下のように[]byte
を作成しencoding/csv
を使用しないでCSVを作成します。
main.go
package main
import (
"fmt"
"os"
"strings"
)
func createByteSlice(s []string) []byte {
str := strings.Join(s, ",")
return []byte(fmt.Sprintf("%s\n", str))
}
func main() {
file, err := os.Create("./fruit.csv")
if err != nil {
panic(err)
}
defer file.Close()
header := []string{"\"name\"", "\"color\"", "\"japanese\""}
records := [][]string{
{"\"apple\"", "\"red\"", "\"りんご\""},
{"\"grape\"", "\"purple\"", "\"ぶどう\""},
{"\"orange\"", "\"orange\"", "\"オレンジ\""},
}
file.Write(createByteSlice(header))
for _, record := range records {
file.Write(createByteSlice(record))
}
}
これを実行すると以下のCSVファイルを作成することができました。
fruit.csv
"name","color","japanese"
"apple","red","りんご"
"grape","purple","ぶどう"
"orange","orange","オレンジ"
おわりに
今回はCSVのフィールドに"
を使用したい場合にGoを使ってどのように作成するかについて解説しました。
ダブルクオートをエスケープするというのはRFC4180で定義されている事項になります。
encoding/csv
パッケージを用いることでよしなに処理してくれるので、通常はencoding/csv
パッケージを使用するといいと思います!