この記事の目標
JavaでCSVファイルを読み書きするライブラリに「Apache Commons CSV」がある。
また、CSVファイルでよく知られた共通フォーマットとして「RFC 4180」がある。しかしこの共通フォーマットが定義される前から広く使われていたためか、CSVファイルには多くの「方言」があるらしい。
comma-separated values(略称:CSV)は、テキストデータをいくつかのフィールド(項目)に分け、区切り文字であるカンマ「,」で区切ったデータ形式。拡張子は .csv、MIMEタイプは text/csv。
出典: ja.wikipedia.org
[広告]関連書籍
サンプルCSVとサンプルプログラム
下記のCSVとプログラムを用いる。また、Apache Commons CSVのバージョンは1.8(2020年2月6日リリース)を使用する。
# ヘッダ行 フィールド1,フィールド2,フィールド3,フィールド4 # 各レコードは改行コードで区切られる 改行,コード,で,区切られる # スペースはそのまま読み込む スペースなし, 前にスペース,後ろにスペース , 前後にスペース # 二重引用符はあってもなくても良い "二重引用符は",あっても,"なくても",良い # 改行コード、コンマを含むフィールドは二重引用符で囲む "改行 改行","コンマ,コンマ",a,b # 二重引用符内の二重引用符は二重引用符を重ねてエスケープ "二重引用符""囲まれた""二重引用符",a,b,c # 最終行は改行コードなしでも良い 最終行は,改行コード,なしでも,良い
try (CSVParser parser = CSVFormat.DEFAULT .withCommentMarker('#') .withFirstRecordAsHeader() .parse(Files.newBufferedReader(csvFilePath))) { for (CSVRecord record : parser) { System.out.println(record); } }
実行結果の確認
実行結果の全体は下記のとおり。以下で1つ1つの結果について確認していく。
CSVRecord [comment='各レコードは改行コードで区切られる', recordNumber=1, values=[改行, コード, で, 区切られる]] CSVRecord [comment='スペースはそのまま読み込む', recordNumber=2, values=[スペースなし, 前にスペース, 後ろにスペース , 前後にスペース ]] CSVRecord [comment='二重引用符はあってもなくても良い', recordNumber=3, values=[二重引用符は, あっても, なくても, 良い]] CSVRecord [comment='改行コード、コンマを含むフィールドは二重引用符で囲む', recordNumber=4, values=[改行 改行, コンマ,コンマ, a, b]] CSVRecord [comment='二重引用符内の二重引用符は二重引用符を重ねてエスケープ', recordNumber=5, values=[二重引用符"囲まれた"二重引用符, a, b, c]] CSVRecord [comment='最終行は改行コードなしでも良い', recordNumber=6, values=[最終行は, 改行コード, なしでも, 良い]]
最初にヘッダ行があっても良い
CSVファイルの最初の行に各フィールドの名前を示すヘッダ行があっても良い。
Apache Commons CSVでは、CSVFormat#withFirstRecordAsHeaderを指定することでヘッダ行を読み飛ばすことができる。
# ヘッダ行 フィールド1,フィールド2,フィールド3,フィールド4
ヘッダ行を読み込んでおくと、レコードから必要なフィールドをフィールド名指定で取得できる。以下はサンプルCSVの4行目のレコードから取得した例。
record.get("フィールド1") ==> 改行 record.get("フィールド2") ==> コード record.get("フィールド3") ==> で record.get("フィールド4") ==> 区切られる
各レコードは改行コードで区切られる
CSVの各レコードは改行コードで区切られる。
# 各レコードは改行コードで区切られる 改行,コード,で,区切られる
CSVRecord [comment='各レコードは改行コードで区切られる', recordNumber=1, values=[改行, コード, で, 区切られる]]
スペースはそのまま読み込む
スペースを含むフィールドはそのまま読み込みトリムはしない。
# スペースはそのまま読み込む スペースなし, 前にスペース,後ろにスペース , 前後にスペース
CSVRecord [comment='スペースはそのまま読み込む', recordNumber=2, values=[スペースなし, 前にスペース, 後ろにスペース , 前後にスペース ]]
二重引用符はあってもなくても良い
各フィールドを二重引用符(ダブルコーテーション)で囲っても良いし囲わなくても良い。
# 二重引用符はあってもなくても良い "二重引用符は",あっても,"なくても",良い
CSVRecord [comment='二重引用符はあってもなくても良い', recordNumber=3, values=[二重引用符は, あっても, なくても, 良い]]
改行コード、コンマを含むフィールドは二重引用符で囲む
改行コードやコンマといった、レコード区切りやフィールド区切りに使われる文字をフィールド内に含めるときは、必ず二重引用符で囲わなければならない。そうしないと意図していないところでレコード区切りやフィールド区切りとみなされてしまうためである。
# 改行コード、コンマを含むフィールドは二重引用符で囲む "改行 改行","コンマ,コンマ",a,b
CSVRecord [comment='改行コード、コンマを含むフィールドは二重引用符で囲む', recordNumber=4, values=[改行 改行, コンマ,コンマ, a, b]]
二重引用符内の二重引用符は二重引用符を重ねてエスケープ
二重引用符の中に二重引用符を入れる場合は、二重引用符を2回続けてエスケープしなければならない。
# 二重引用符内の二重引用符は二重引用符を重ねてエスケープ "二重引用符""囲まれた""二重引用符",a,b,c
CSVRecord [comment='二重引用符内の二重引用符は二重引用符を重ねてエスケープ', recordNumber=5, values=[二重引用符"囲まれた"二重引用符, a, b, c]]
最終行は改行コードなしでも良い
各レコードは改行コードで区切るが、最終行は改行コードがなくても良い。
# 最終行は改行コードなしでも良い 最終行は,改行コード,なしでも,良い
CSVRecord [comment='最終行は改行コードなしでも良い', recordNumber=6, values=[最終行は, 改行コード, なしでも, 良い]]
まとめ
Apache Commons CSVがRFC 4180の主要な仕様をすべて満たすことが確認できた。これを使えば主要なCSVファイルは読み込むことができそうだ。
コメント