8
6

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 3 years have passed since last update.

SuperCSVで、和名ヘッダーのCSVからBeanをとりこむ

Last updated at Posted at 2016-03-04

Super CSVでBeanのリストを和名ヘッダーをつけてCSV出力 を以前書いて、入力のときに同じことができないかをやってみました。

結論としてはできます! これで落ち着いてCSV生活がおくれるというものです。

補足

2020年6月時点ですが、supercsvは新しいメンテナーを探している状況です。
最初に作った人が、時間もとれなくなり、モチベーションも下がったとのことです。
詳細はこちら

このissueをみるに、立候補している人が最近出たようですが、どうなるか微妙です。
Javaのライフサイクルも変わったので、これから新しいプロジェクトに使うには躊躇うところです。
(結構使い勝手がよく、日本ではマッチするケースが多い気がするだけに、悩みどころです)

代替のライブラリとしては、univocity_parsers を見つけました。
サンプルコードもたくさん提供されています。

参考リンク

前提

Beanは次のようなものとします。getter,setterは省略しています。
読み取りの場合、setterは必須です。

 class User {
           /**
            * ユーザID
            */   
           private String id;
   
           /**
            * ユーザ名
            */ 
           private String name;

           /**
            * 削除フラグ
            */
           private boolean deleted;

           /* 中略 */ 
        }

また、和名からカラム名へ変換するメソッドを事前に用意します。

// サンプルなので、guavaつかってそれっぽいのを作成
// 実際には設定ファイルなどから生成をするのを想定
Map<String,String> converter = ImmutableMap.Builder()
                               .put("ユーザID", "id")
                               .put("ユーザ名", "name")
                               .put("削除フラグ", "deleted")
                               .build();

public String[] toPropertyHeader(String[] header, Map<String,String> converter) {
   /* converterをつかって、和名をカラム名に変化したarrayを生成 */
}

サンプルコード

次のようなCSVをとりこむとします。

user.csv
ユーザID,ユーザ名,削除フラグ
001,ユーザその1,false
002,ユーザ2,true
   File file = new File("user.csv");
   try(ICsvBeanReader beanReader = new CsvMapReader(new FileReader(file), CsvPreference.EXCEL_PREFERENCE)) {
            String[] header = beanReader .getHeader(true); // CSVの和名ヘッダーを取得          
            String[] propertyHeader = toPropertyHeader(header, converter); //和名ヘッダーをカラム名ヘッダーに変換

            User user;
            while((user= beanReader .read(User.class, propertyHeader)) != null) {
                Logger.info("user {}", user);
            }
        } catch (Exception e) {
            Logger.error("reading is failed.", e);
        }


ポイントなのは、getHeaderで取得したのを変換するところです。
readerは、ヘッダー内のカラムの順番で値を持っているので、実際に渡されたヘッダー内の順番を保持する必要があります。こうした場合、ヘッダーの中の順番をかえても、結果的には名前でマッピングされているので、正しくとりこめます。

まとめ

Beanでやりました、Mapでもどうようのことができます。公式サイトをよく読んでみたら、

This relies on the fact that the column names in the header of the CSV file

customerNo,firstName,lastName,birthDate,mailingAddress,married,numberOfKids,favouriteQuote,email,loyaltyPoints

match up exactly with the bean's field names, and the bean has the appropriate setters defined for each field.

If your header doesn't match (or there is no header), then you can simply define your own name mapping array.

とあるので、もとのヘッダーがカラム名になってなかったら、自分で用意できるよということですね。もっとはやく気がつけば...

8
6
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
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?