54
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaのCSVライブラリ「opencsv」

Last updated at Posted at 2018-03-06

業務でJavaのCSVライブラリを探して使用したので、備忘録としてまとめていきます。
#JavaのCSVライブラリの一覧(2018.01時点)
JavaでCSVライブラリは下記のものがあります。

今回はopencsvを使用しました。
#環境

  • Java 8
  • Gradle 4.1
  • opencsv 4.1

opencsv 4 はjava7以降が対応です。
また、opencsv3.xとopencsv4.xでは使い方が異なりますので注意してください。

#やりたいこと
こんな内容のCSVファイル(item.csv)の読取と出力を行います。

item.csv
"商品ID","商品名","単価","数量"
001,"ポテトチップス",150,50
002,"チョコレート",100,30
003,"アイス",120,10

ポイントは3点です。

  • ヘッダーつき(日本語)
  • セパレータはカンマ
  • 文字列はダブルクォート「"」でくくる

#準備
Gradleのdependencyにopencsvを追加します。
commons-loggingをexcludeしている場合はコメントアウトしてください。実行時に例外が発生します。

build.gradle
    //下記の記載がある場合はコメントアウトが必要
   configurations {
        //all*.exclude module: 'commons-logging'
   }

    dependencies {
        compileOnly group:'org.projectlombok', name:'lombok', version:'1.16.20'
        //csv library
        implementation group:'com.opencsv', name:'opencsv', version:'4.1'
        implementation group:'commons-logging', name: 'commons-logging', version:'1.2'
    }

また、CSVファイルの項目に合わせたEntityクラスを用意します。
Entityクラスのフィールドにアノテーションを付加することで、EntityクラスとCSVファイルのカラムを紐付けます。

アノテーションは取り込みパターンに応じて2種類から選択できます。

  • @CsvBindByName ヘッダーカラムとフィールドを紐付け
  • @CsvBindByPosition 入力順とフィールドを紐付け(ヘッダーつきのため今回は除外します)

@CsvBindByNameを使用する場合

ItemEntity.java
package entity;

import com.opencsv.bean.CsvBindByName;

import lombok.Data;

/**
 * 商品を管理するEntityクラス。
 */
@Data
public class ItemEntity {

	@CsvBindByName(column = "商品ID", required = true)
	private String id;

	@CsvBindByName(column = "商品名", required = true)
	private String name;

	@CsvBindByName(column = "単価", required = true)
	private int price;

	@CsvBindByName(column = "数量", required = true)
	private int amount;
}

@CsvBindByPositionを使用する場合

ItemEntity2.java
package entity;

import com.opencsv.bean.CsvBindByPosition;

import lombok.Data;

/**
 * 商品を管理するEntityクラス。
 */
@Data
public class ItemEntity2 {

	@CsvBindByPosition(position = 0, required = true)
	private String id;

	@CsvBindByPosition(position = 1, required = true)
	private String name;

	@CsvBindByPosition(position = 2, required = true)
	private int price;

	@CsvBindByPosition(position = 3, required = true)
	private int amount;
}

#CSV読み取り
CSV読み取りのコードサンプルです。

ItemFileDao.java
CsvToBean<ItemEntity> csvToBean = new CsvToBeanBuilder<ItemEntity>(reader).withType(ItemEntity.class).build();
List<ItemEntity> items = csvToBean.parse();

CsvToBeanBuilder クラスを使用します。
CsvToBeanBuilder#withType メソッドまたは CsvToBeanBuilder#withMappingStrategy メソッドを必ず呼び出してください。
セパレータを指定する場合は CsvToBeanBuilder#withSeparator メソッドを使用してください。

コードサンプルでは @CsvBindByName を使用したEntityクラスを使用しています。
@CsvBindByPosition を使用したEntityクラスの場合、ヘッダーがなければ同様の結果が得られます。

#CSV出力
CSV出力のコードサンプルです。

ItemFileDao.java
StatefulBeanToCsv<ItemEntity> beanToCsv = new StatefulBeanToCsvBuilder<ItemEntity>(writer).build();
beanToCsv.write(beans);

StatefulBeanToCsvBuilder クラスを使用します。
セパレータを指定する場合は CsvToBeanBuilder#withSeparator メソッドを使用してください。

@CsvBindByName を使用したEntityクラスを使用した場合、ヘッダーは自動で付加されますが、カラムの順番はヘッダーの文字コード順(?)となるようです。
@CsvBindByPosition を使用したEntityクラスを使用した場合、ヘッダーは自動で付加されません。

#サンプルコードと実行結果

ItemFileDao.java

import java.io.Reader;
import java.io.Writer;
import java.util.List;

import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;
import com.opencsv.exceptions.CsvException;

/**
 * CSVファイルとのやり取りを行うDaoクラス。
 */
public class ItemFileDao {

	public void write(Writer writer, List<ItemEntity> beans) throws CsvException {
		StatefulBeanToCsv<ItemEntity> beanToCsv = new StatefulBeanToCsvBuilder<ItemEntity>(writer).build();
		beanToCsv.write(beans);
	}
	public List<ItemEntity> read(Reader reader) throws CsvException {
		CsvToBean<ItemEntity> csvToBean = new CsvToBeanBuilder<ItemEntity>(reader).withType(ItemEntity.class).build();
		return csvToBean.parse();
	}
}
Main.java
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import com.opencsv.exceptions.CsvException;

public class Main {

	public static void main(String[] args) {

		ItemFileDao csvFileDao = new ItemFileDao();
		
		try (Reader reader = Files.newBufferedReader(Paths.get("item.csv"));
				Writer writer = Files.newBufferedWriter(Paths.get("item2.csv"));) {
			List<ItemEntity> items = csvFileDao.read(reader);
			items.forEach(System.out::println);
			csvFileDao.write(writer, items);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (CsvException e) {
			e.printStackTrace();
		}
	}
}
ItemEntity(id=001, name=ポテトチップス, price=150, amount=50)
ItemEntity(id=002, name=チョコレート, price=100, amount=30)
ItemEntity(id=003, name=アイス, price=120, amount=10)
item2.csv
"単価","商品ID","商品名","数量"
"150","001","ポテトチップス","50"
"100","002","チョコレート","30"
"120","003","アイス","10"
54
43
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
54
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?