バックエンド

【Java】Super CSV & Super CSV Annotationの使い方!【ライブラリ】

super-csv

こんばんは!光です。

大手グローバル企業でWebエンジニアをやっています。

Webエンジニアを目指してプログラミングを勉強している初心者の方向けに情報を発信しています。

経歴や実績はこちら

システム開発のお仕事の依頼もお待ちしております。

お問い合わせページTwitterのDMからお気軽にお問い合わせください!

今回はこのような質問をいただきました。

JavaでCSVを扱うときのライブラリって何が良いんだろう?

CSVの処理はライブラリを使うだけでかなり効率的になります。

そこで今回はJavaのCSVライブラリ、Super CSVについて解説していきます!

環境
  • Java 11
  • Play framework 2.6
  • Super CSV 2.4.0
  • Super CSV Annotation 2.2

Super CSVを実際に使ってみよう!

今回はサンプルとして店舗情報のCSVを用意しました。

店舗ID,店舗名,電話番号
1,A店,0000000001
2,B店,0000000002
3,C店,0000000003
店舗ID店舗名電話番号
1A店0000000001
2B店0000000002
3C店0000000003

こんな感じのCSVを取り込んでみます。

ライブラリのインポート

今回、私はPlay Framework 2.6で使用しました。

Super CSVを使えるようにするためにbuild.sbtに追記します。

バージョンは最新ものもにしたほうが良いと思います。

super-csv-annotationも必要になるのでここで追加します。

libraryDependencies += "net.sf.supercsv" % "super-csv" % "2.4.0"
libraryDependencies += "com.github.mygreen" % "super-csv-annotation" % "2.2"

DTOの作成

CSVから変換するDTOを作成します。

import com.github.mygreen.supercsv.annotation.CsvBean;
import com.github.mygreen.supercsv.annotation.CsvColumn;

/**
 * 店舗DTO
 */
@CsvBean(header = true)
public class SampleShopDto {
    /**
     * 店舗ID
     */
    @CsvColumn(number = 1, label = "店舗ID")
    public String id;

    /**
     * 店舗名
     */
    @CsvColumn(number = 2, label = "店舗名")
    public String name;

    /**
     * 電話番号
     */
    @CsvColumn(number = 3, label = "電話番号")
    public String tel;

    public SampleShopDto() {
    }
}

CSV読み込み・書き出し処理

今回は共通処理として作ってみました。

第三引数を切り替えることでTSVも変換できます。

CSVとTSVを両方使う場面も多いと思うので、ライブラリ側で対応されているのはありがたいですね!

/**
 * CSVファイルを読み込む
 * @param path ファイルパス
 * @param clazz Beanクラス
 * @param csvPreference CSV(STANDARD_PREFERENCE) or TSV(TAB_PREFERENCE)
 * @return List
 */
public static <T> List<T> readCsv(String path, Class<T> clazz, CsvPreference csvPreference) {
    try (
            CsvAnnotationBeanReader<T> csvReader = new CsvAnnotationBeanReader<>(
                    clazz,
                    Files.newBufferedReader(new File(path).toPath(), Charset.defaultCharset()),
                    csvPreference
            )
    ) {
        return csvReader.readAll();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

/**
 * CSVファイルを書き出す
 * @param path 保存先
 * @param clazz Beanクラス
 * @param csvPreference CSV(STANDARD_PREFERENCE) or TSV(TAB_PREFERENCE)
 * @param list データ
 */
public static <T> void writeCsv(String path, Class<T> clazz, CsvPreference csvPreference, List<T> list) {
    try (
            CsvAnnotationBeanWriter<T> csvWriter = new CsvAnnotationBeanWriter<>(
                    clazz,
                    Files.newBufferedWriter(new File(path).toPath(), Charset.defaultCharset()),
                    csvPreference
            )
    ) {
        csvWriter.writeAll(list);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

読み込み

あとはこんな感じでメソッドを呼んであげるだけ!

final String PATH = "XXXXXXXXX";
List<SampleShopDto> sampleShopDtoList = readCsv(PATH + "sample.csv", SampleShopDto.class, CsvPreference.STANDARD_PREFERENCE);
sampleShopDtoList.forEach(sampleShopDto -> {
    System.out.println(sampleShopDto.id + " ," + sampleShopDto.name + ", " + sampleShopDto.tel);
});
1 ,A店, 0000000001
2 ,B店, 0000000002
3 ,C店, 0000000003

PATHは自分がCSVを配置したディレクトリを指定してください。

ちなみにディレクトリはパーミッション変更しておかないとCSVを読み込めないです。

書き出し

書き出しの場合はこんな感じ。

final String PATH = "XXXXXXXXX";
SampleShopDto sampleShopDto = new SampleShopDto();
sampleShopDto.id = "4";
sampleShopDto.name = "D店";
sampleShopDto.tel = "0000000004";
List<SampleShopDto> sampleShopDtoList = Collections.singletonList(sampleShopDto);
writeCsv(PATH + "sample2.csv", SampleShopDto.class, CsvPreference.STANDARD_PREFERENCE, sampleShopDtoList);

読み込みの処理を逆にしただけですね。

店舗ID,店舗名,電話番号
4,D店,0000000004
店舗ID店舗名電話番号
4D店0000000004

まとめ

Super CSVとSuper CSV Annotationをインポートして以下のメソッドを呼び出すだけ!

/**
 * CSVファイルを読み込む
 * @param path ファイルパス
 * @param clazz Beanクラス
 * @param csvPreference CSV(STANDARD_PREFERENCE) or TSV(TAB_PREFERENCE)
 * @return List
 */
public static <T> List<T> readCsv(String path, Class<T> clazz, CsvPreference csvPreference) {
    try (
            CsvAnnotationBeanReader<T> csvReader = new CsvAnnotationBeanReader<>(
                    clazz,
                    Files.newBufferedReader(new File(path).toPath(), Charset.defaultCharset()),
                    csvPreference
            )
    ) {
        return csvReader.readAll();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

/**
 * CSVファイルを書き出す
 * @param path 保存先
 * @param clazz Beanクラス
 * @param csvPreference CSV(STANDARD_PREFERENCE) or TSV(TAB_PREFERENCE)
 * @param list データ
 */
public static <T> void writeCsv(String path, Class<T> clazz, CsvPreference csvPreference, List<T> list) {
    try (
            CsvAnnotationBeanWriter<T> csvWriter = new CsvAnnotationBeanWriter<>(
                    clazz,
                    Files.newBufferedWriter(new File(path).toPath(), Charset.defaultCharset()),
                    csvPreference
            )
    ) {
        csvWriter.writeAll(list);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

汎用的なメソッドになっているので、必要であれば自分の使いやすいようにアレンジしてみてください!

あとがき

Super CSVを使ってCSVを処理してみました。

難しい部分はすべてライブラリがやってくれるので簡単ですね。

自分で実装するよりもシンプルに実装できるので保守もしやすくなると思います。

独自で処理を作成するよりも簡単なので是非使ってみてください!