Super CSV Annotation 2.0のリリース
久しぶりの更新です。
JavaでCSVファイルを扱うためのライブラリ Super CSV に対してアノテーション機能を付け加えた独自のライブラリ Super CSV Annotation のver2.0をリリースしました。
- マニュアル
- ソース(GitHub)
主な変更点
作り直したため、互換性はなくなりましたが、基本的な使用方法は変わりません。
パッケージ名、クラス名は大きく変わっています。
- トリムなどの変換用のアノテーションを追加。
- 今までは、XXXConverterアノテーションに集約していたものを分離しました。
- バリデーション用のアノテーションを追加。
- これも、XXXConverterアノテーションに集約していたものを分離しました。
- 書式指定用のアノテーションを変更。
- 今までは、XXXConverterという名称から、XXXFormatに変更しました。
- BeanValdiationのように各種アノテーションを合成して、新たなアノテーションが作成できます。
機能的には変わりませんが、上記の機能に対する独自の拡張やアノテーションの追加が圧倒的に容易にできるようになりました。
機能一覧は、マニュアルの目次 を見ていただければわかります。
また、Bean Validationのように属性「groups」でアノテーションを適用するケースを絞り込めるようにしました。
よく使う、読み込み、書き込み時の区別は、別な属性「cases」でできるようにしました。
さらに、Bean Validationの使い勝手の悪い、順番の指定ができるようにしています。
順番や適用するケースが指定できることで、かなり柔軟な加工ができるようになりました。
まあ、現在、仕様策定中の Bean Validation 2.0 からは順番の指定ができるようになるそうですが。
基本的な使い方
マニュアルの内容そのままです。
pom.xmlには下記を追加。
<dependency> <groupId>com.github.mygreen</groupId> <artifactId>super-csv-annotation</artifactId> <version>2.0</version> </dependency>
Beanの定義
基本的なアノテーション @CsvBean、@CsvColumn は変わりません。
ただし、@CsvColumnの番号指定は index→numberに代わり、1から指定するようにしました。
カラム数が多くなるとこれは設計書からBeanを定義するとき、個人的によくずれて定義してしまったためです。
import java.time.LocalDate; import com.github.mygreen.supercsv.annotation.CsvBean; import com.github.mygreen.supercsv.annotation.CsvColumn; import com.github.mygreen.supercsv.annotation.constraint.CsvNumberMin; import com.github.mygreen.supercsv.annotation.constraint.CsvRequire; import com.github.mygreen.supercsv.annotation.constraint.CsvUnique; import com.github.mygreen.supercsv.annotation.conversion.CsvDefaultValue; import com.github.mygreen.supercsv.annotation.conversion.CsvNullConvert; import com.github.mygreen.supercsv.annotation.format.CsvDateTimeFormat; import com.github.mygreen.supercsv.annotation.format.CsvNumberFormat; import com.github.mygreen.supercsv.builder.BuildCase; @CsvBean public class SampleCsv { @CsvColumn(number=1, label="ID") @CsvRequire // 必須チェックを行う @CsvUnique(order=1) // 全レコード内で値がユニークかチェックする(順番指定) @CsvNumberMin(value="0", order=2) // 最小値かどかチェックする(順番指定) private Integer id; @CsvColumn(number=2, label="名前") private String name; @CsvColumn(number=3, label="誕生日") @CsvDateTimeFormat(pattern="yyyy年MM月dd日") // 日時の書式を指定する private LocalDate birthday; @CsvColumn(number=4, label="給料") @CsvNumberFormat(pattern="#,###0") // 数値の書式を指定する @CsvDefaultValue(value="N/A", cases=BuildCase.Write) // 書き込み時に値がnull(空)の場合、「N/A」として出力します。 @CsvNullConvert(value="N/A", cases=BuildCase.Read) // 読み込み時に値が「N/A」のとき、nullとして読み込みます。 private Integer salary; // getter/setterは省略 }
読み書きの方法
読み書きするためのクラス CsvAnnotationBeanReader/CsvAnnotationBeanWriterは大きく変わりません。
ただし、一度に読み書きする readAll()/writeAll() メソッドを追加しました。
import com.github.mygreen.supercsv.io.CsvAnnotationBeanReader; import com.github.mygreen.supercsv.io.CsvAnnotationBeanWriter; import java.nio.charset.Charset; import java.nio.file.Files; import java.io.File; import java.util.ArrayList; import java.util.List; import org.supercsv.prefs.CsvPreference; public class Sample { // 全レコードを一度に読み込む場合 public void sampleReadAll() { CsvAnnotationBeanReader<SampleCsv > csvReader = new CsvAnnotationBeanReader<>( SampleCsv .class, Files.newBufferedReader(new File("sample.csv").toPath(), Charset.forName("Windows-31j")), CsvPreference.STANDARD_PREFERENCE); List<SampleCsv > list = csvReader.readAll(); csvReader.close(); } // レコードを1件ずつ読み込む場合 public void sampleRead() { CsvAnnotationBeanReader<SampleCsv > csvReader = new CsvAnnotationBeanReader<>( SampleCsv .class, Files.newBufferedReader(new File("sample.csv").toPath(), Charset.forName("Windows-31j")), CsvPreference.STANDARD_PREFERENCE); List<SampleCsv > list = new ArrayList<>(); // ヘッダー行の読み込み String headers[] = csvReader.getHeader(true); UserCsv record = null; while((record = csvReader.read()) != null) { list.add(record); } csvReader.close(); } // 全レコードを一度に書き込む場合 public void sampleWriteAll() { CsvAnnotationBeanWriter<UserCsv> csvWriter = new CsvAnnotationBeanWriter<>( UserCsv.class, Files.newBufferedWriter(new File("sample.csv").toPath(), Charset.forName("Windows-31j")), CsvPreference.STANDARD_PREFERENCE); // 書き込み用のデータの作成 List<SampleCsv > list = new ArrayList<>(); SampleCsv record1 = new SampleCsv (); record1.setNo(1); record1.setName("山田太郎"); liad.add(record1); SampleCsv record2 = new SampleCsv (); record2.setNo(2); record2.setName("鈴木次郎"); liad.add(record2); // ヘッダー行と全レコードデータの書き込み csvWriter.writeAll(list); csvWriter.close(); } // レコードを1件ずつ読み込む場合 public void sampleWrite() { CsvAnnotationBeanWriter<SampleCsv > csvWriter = new CsvAnnotationBeanWriter<>( SampleCsv .class, Files.newBufferedWriter(new File("sample.csv").toPath(), Charset.forName("Windows-31j")), CsvPreference.STANDARD_PREFERENCE); // ヘッダー行の書き込み csvWriter.writeHeader(); // レコードのデータの書き込み SampleCsv record1 = new SampleCsv (); record1.setNo(1); record1.setName("山田太郎"); csvWriter.write(record1); SampleCsv record2 = new SampleCsv (); record2.setNo(2); record2.setName("鈴木次郎"); csvWriter.write(record2); csvWrier.flush(); csvWrier.close(); } }