###前提・実現したいこと
- 目的
CSVファイルを取り込み、変換した後、再びCSVファイルに書き出すツールを作成しております
- 環境
- windows7
- go1.6.3 windows/amd64
- CSV
- 変換前
取り込むCSVは要素がダブルクオートでくくられたカンマ区切りで区切られ、
改行(CRLF)で区切られています
"test1","test2","test3" "test1","test2","test3" "test1","test2","test3"
- 変換後
一旦変換内容は問わず、以下のように再びダブルクオートでくくられたCSVファイルを出力しようとしております
"test1","test2","test3" "test1","test2","test3" "test1","test2","test3"
###発生している問題
- 事象
CSVを再出力するとき、要素を区切るダブルクオートをうまく出力することができません
ダブルクオートを表示しようとした場合、重複して出力されるなどの動きになってしまいます。以下ソースで説明いたします
###該当のソースコード
go
1package main 2 3import ( 4 "encoding/csv" 5 "io" 6 "flag" 7 "log" 8 "os" 9) 10 11func failOnError(err error) { 12 if err != nil { 13 log.Fatal("Error:", err) 14 } 15} 16 17func main() { 18 flag.Parse() 19 20 // 入力CSV 21 file1, err := os.Open("data/input_T.csv") 22 failOnError(err) 23 defer file1.Close() 24 25 // 出力CSV 26 file2, err := os.Create("data/test_o2.csv") 27 failOnError(err) 28 defer file2.Close() 29 reader := csv.NewReader(file1) //utf8 30 31 writer := csv.NewWriter(file2) //utf8 32 writer.UseCRLF = true //デフォルトはLFのみ 33 34 log.Printf("Start") 35 for { 36 record, err := reader.Read() // 1行読み出す 37 if err == io.EOF { 38 break 39 } else { 40 failOnError(err) 41 } 42 var new_record []string 43 for i, v := range record { 44 if i >= 0 { 45 new_record = append(new_record, v) 46 } 47 } 48 writer.Write(new_record) // 1行書き出す 49 } 50 writer.Flush() 51 log.Printf("Finish !") 52} 53
- 最初のCSVを登録したとき、
この場合は
test1,test2,test3 test1,test2,test3 test1,test2,test3
のように、要素をくくるダブルクオートが表示されない状態で出力されます
そこで以下のように、出力するCSVの配列を作成するとき、
要素をエスケープしたダブルクオートで文字列結合した状態で格納します
go
1for i, v := range record { 2 if i >= 0 { 3 new_record = append(new_record, "\"" + v + "\"") 4 } 5 } 6 writer.Write(new_record) // 1行書き出す
\ はバックスラッシュでダブルクオートをエスケープしています
エスケープを`(バッククオート)でくくった場合も同様の結果となります
"""test1""","""test2""","""test3""" """test1""","""test2""","""test3""" """test1""","""test2""","""test3"""
なぜダブルクオートが3つ重なるのか
- ちなみに、以下のように片側だけにダブルクオートをつけた場合
go
1for i, v := range record { 2 if i >= 0 { 3 new_record = append(new_record, v + "\"") 4 } 5 } 6 writer.Write(new_record) // 1行書き出す
ダブルクオートを付加していない方はひとつ、つけたほうは3つつきます。
"test1""","test2""","test3"""
- シングルクオートでくくった場合
go
1for i, v := range record { 2 if i >= 0 { 3 new_record = append(new_record, "'" + v + "'") 4 } 5 } 6 writer.Write(new_record) // 1行書き出す
シングルクオートでくくった場合は、想定に近い動きをします
'test1','test2','test3'
ダブルクオートで要素をくくった場合だけ、うまくいきません。
- エスケープし、またはダブルクオートの文字列結合の方法に問題があるのでしょうか、
- または、要素をくくる文字を制御する設定がなにかあるのでしょうか。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/08/01 00:38
2016/08/01 01:09