1. アノテーション
まずはBeanのフィールドに指定するアノテーションです。CSVを読み込んだときに、このアノテーションが宣言されているフィールドに対して、値を設定します。
/**
* CSVデータの保持対象を表すアノテーションです。
* このアノテーションはビーンクラスのフィールドに対して宣言します。
*
* @author namiki
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface CsvColumns {
/**
* CSVのカラム順を指定します。
*
* @return カラム順
*/
int index();
}
indexでCSVの何カラム目を設定するか、指定します。2. 任意のBean
続いてCSVの内容を設定するBeanです。
public class Entity {
@CsvColumns(index = 0)
public Integer id;
@CsvColumns(index = 2)
public String name;
@CsvColumns(index = 1)
public String email;
}
Seasar2には依存していませんが、基本的にSeasar2環境で使うことを想定しているため、publicフィールドを採用しています。3. CSVParser
最後にCSVを読み込むためのクラスです。
/**
* CSVファイルを読み込み、型パラメータで指定されたクラスのリストを作成するクラスです。
*
* @author namiki
*
*/
public class CsvFileParser<T> {
// ------------------------------------------------------------- [Constants]
/** CSVの区切り文字です。 */
private static final String DELIMITER = ",";
// ------------------------------------------------------------ [Properties]
/** 読込対象ファイルです。 */
private File target;
// ----------------------------------------------------------- [Constructor]
/**
* コンストラクタです。
*
* @param target
* 対象ファイル
*/
public DcssCsvFileParser(File target) {
this.target = target;
}
// -------------------------------------------------------- [Public methods]
/**
* CSVファイルを読込み、型パラメータで指定されたクラスのリストを返します。
*
* @param c
* 型
* @return リスト
*/
@SuppressWarnings("unchecked")
public List<T> readLines(Class<T> c) {
List<Object> list = new ArrayList<Object>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(target));
String line = null;
while ((line = reader.readLine()) != null) {
String[] array = line.split(DELIMITER);
Object entity = c.newInstance();
Field[] fields = c.getFields();
for (Field field : fields) {
CsvColumns col = field.getAnnotation(CsvColumns.class);
if (null != col) {
if (field.getType() == Integer.class) {
field.set(entity, Integer
.valueOf(array[col.index()]));
} else if (field.getType() == Long.class) {
field.set(entity, Long.valueOf(array[col.index()]));
} else {
field.set(entity, array[col.index()]);
}
}
}
list.add(entity);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(reader);
}
return (List<T>) list;
}
}
4. 使い方
最後にこのクラスの使い方です。
CsvFileParserGenericsやらClass指定やらが続いて、少し気持ち悪いですね…。ちょっとここら辺は直したいところですが、取り敢えずこんな感じでCSV読み込みを簡略化することができました。parser = new CsvFileParser (file); List list = parser.readLines(Entity.class);
ただあまりCSVの行数が多いとOutOfMemoryになってしまいそうなので注意が必要ですね。そこら辺も合わせてもう少し手を入れていこうと思います。