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になってしまいそうなので注意が必要ですね。そこら辺も合わせてもう少し手を入れていこうと思います。
 

0 件のコメント:
コメントを投稿