LoginSignup
6
11

More than 5 years have passed since last update.

Apache Commons CSVによるCSV出力

Posted at

はじめに

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メソッドと同時に使おうとしても区切り文字は入れてくれない。

printとprintRecordの併用
printer.print("test1");
printer.print("test2");
printer.printRecord("test3", "test4");
出力
test1,test2test3,test4

その他コメントを出力するprintCommentメソッドや、1レコードではなく複数行を出力するprintRecordsメソッドなんかもある(printRecordsにいたってはResultSetを引数に取れたりする)ので、必要に応じて使い分けるのがよいだろう。

CSV形式

CSVFormatの使い方によっては、あらかじめCSVの形式に手を加えることができる。下記の例では、あらかじめヘッダー行を追加し、区切り文字をタブ文字に変更している。

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扱いたい。

6
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
11