はじめに
CSVを出力するのはさほど難しいことではないが、一応いくつか仕様のようなものがあり、知らずに出力すると仕様を無視したものが出来上がってしまうことがあり得る。というか近いことをやりかけたことがある。
仕様自体はwikiでも公式仕様でも確認すればよいが、JavaはApacheがCSVを読み書きするためのライブラリを公開していたりするので、こちらを使った出力についてまとめた。読み込みはやらない。
公式マニュアル
基本
Javadoc
初期設定について
https://mvnrepository.com/artifact/org.apache.commons/commons-csv
MavenやGradleを使う場合は上記を参考にしてgroupId等を取得すればよい。
一応公式がダウンロードリンクを公開していたりもするので、こちらからダウンロードして動かすこともできるはず(未確認)。
基本的な使い方
JavadocのCSVPrinterのところに簡単な例が記述してある。
try (CSVPrinter printer = new CSVPrinter(new FileWriter("csv.txt"), CSVFormat.EXCEL)) {
printer.printRecord("id", "userName", "firstName", "lastName", "birthday");
printer.printRecord(1, "john73", "John", "Doe", LocalDate.of(1973, 9, 15));
printer.println();
printer.printRecord(2, "mary", "Mary", "Meyer", LocalDate.of(1985, 3, 29));
} catch (IOException ex) {
ex.printStackTrace();
}
id,userName,firstName,lastName,birthday
1,john73,John,Doe,1973-09-15
2,mary,Mary,Meyer,1985-03-29
以下解説。
CSVPrinter printer = new CSVPrinter(new FileWriter("csv.txt"), CSVFormat.EXCEL)
CSVPrinter
がCSV出力用のインスタンス。CSVFormat.EXCEL
がCSV出力時の形式である。基本的にはRFC4180をベースにしたDEFAULT(ただし若干違いあり)やEXCELファイルの仕様に沿ったEXCELを使えばよいと思うが、一応ほかにも色々あるので公式のJavadocを確認してみるのが良い。
それぞれの違いもJavadocを確認すればわかるが、一部CSVの読み込みにしか関係しない設定もある。
printer.printRecord("id", "userName", "firstName", "lastName", "birthday");
printer.printRecord(1, "john73", "John", "Doe", LocalDate.of(1973, 9, 15));
printer.println();
printer.printRecord(2, "mary", "Mary", "Meyer", LocalDate.of(1985, 3, 29));
printRecord
で1行分のデータが出力される。引数はObject
なので文字列以外も受け取れる。println
で改行。
なお値の中に区切り文字が含まれていれば、形式に沿った形で出力される(CSVFormat.EXCEL
なら値が"
で囲まれた状態で出力される)。
printer.printRecord("te,st", "テスト");
"te,st",テスト
その他の使い方について
出力
printメソッドを使うことで、1レコードごとではなく1つの値ごとに出力することができる。連続して実行すれば自動で区切り文字を入れてくれるが、同じ行の中でprintRecord
メソッドと同時に使おうとしても区切り文字は入れてくれない。
printer.print("test1");
printer.print("test2");
printer.printRecord("test3", "test4");
test1,test2test3,test4
その他コメントを出力するprintCommentメソッドや、1レコードではなく複数行を出力するprintRecordsメソッドなんかもある(printRecords
にいたってはResultSetを引数に取れたりする)ので、必要に応じて使い分けるのがよいだろう。
CSV形式
CSVFormat
の使い方によっては、あらかじめCSVの形式に手を加えることができる。下記の例では、あらかじめヘッダー行を追加し、区切り文字をタブ文字に変更している。
CSVPrinter printer =
CSVFormat.DEFAULT.withHeader("ヘッダー1", "ヘッダー2", "ヘッダー3").withDelimiter('\t').print(writer);
printer.printRecord("a", "b", "c");
ヘッダー1 ヘッダー2 ヘッダー3
a b c
withHeader
メソッドでヘッダー行を追加し、withDelimiter
メソッドで区切り文字を変更している。最後のprint
メソッドはCSVPrinter
のインスタンスを取得するためのもの。
ほかにも色々あるのでこれらを使うことで作成するCSVの形式をいろいろいじれるようになるが、よくわからないCSVを作成することでほかのアプリケーションからCSVとして読み込まれないようになるなんてことはないようにしたい。
おわりに
標準機能でCSV扱いたい。