😺

Goでencoding/csvでフィールド数が異なるファイルを読み取る

2023/09/12に公開

Go言語の標準ライブラリの一つであるencoding/csv を使ってcsvを読み込んだ場合、フィールドの数はヘッダ部分も含めて同じであることが前提となっています。

CSVの読み取りに使う関数である Reader.Read() の返り値定義は (record []string, err error) です。もしも、途中にフィールド数が異なるレコードがある場合、 Reader.Read() の返り値のerrに csv.ErrFieldCount が入って返ってきます。

しかし、実はこの時 record の中にそれまで読み取れた値が入っています。そのため、以下のようにすれば処理を継続できます。

record, err := r.Read()
if err == io.EOF {
	break
}
if err != nil && err != csv.ErrFieldCount {
	return inv, rec, err
}

fmt.Println(record) // 値がある!

この挙動は Reader.Read に以下のように記載されています。

If the record has an unexpected number of fields, Read returns the record along with the error ErrFieldCount.

通常goではerrがnilではない場合、それ以外の値になにが入っているかは実装依存なのであまりその値を使うことはないのですが、このRead関数に限っては明示的にドキュメントに記載されていますので使ってもよいと思います。

ちなみに、以下のようにも書いていますので、行の途中で ErrFieldCount 以外のエラーが出た場合でもそれまで読み取れた値が入ってたりします。

If the record contains a field that cannot be parsed, Read returns a partial record along with the parse error. The partial record contains all fields read before the error.

Discussion