BeanIOでCSVや固定長データとJavaクラスをマッピング

# BeanIOとは
ApacheのJavaライブラリ。CSV・固定長データ・XMLなどをJavaクラスにマッピングできる。
ここ数年更新されておらず、日本語の記事も皆無なので、このライブラリを使うのがベストなのか分からないけど、特定の場面では有効かなと思います。

リファレンス（英語）はこちら。
http://beanio.org/2.1/docs/reference/index.html#FixedLengthStreamFormat
英語読める人はリファレンス読めばいいけど、所どころサンプルコードに間違いがあったので注意して下さい。
# 導入
Mavenの場合。

    <dependency>
      <groupId>org.beanio</groupId>
      <artifactId>beanio</artifactId>
      <version>2.1.0</version>
    </dependency>

zipはこちら。
https://code.google.com/archive/p/beanio/downloads
# CSV→オブジェクト
手始めにCSV→オブジェクトのマッピングをしてみる。
まず、CSVファイルと、CSVの各項目に対応するフィールドを持つクラスを作成する。

#### CSVファイル

```employee.csv
Joe,Smith,11000000,20091001,Developer
Jane,Doe,12000000,20080115,Architect
Jon,Anderson,6000000,20100318,Manager
```


#### マッピングするクラス

```Employee.java
package example;
import java.util.Date;

public class Employee {
    String firstName;
    String lastName;
    int salary;
    Date hireDate;
    String title;
    // 省略しているが、getter,setterも必要
}
```

で、CSVとクラスのマッピング定義を作成する。

#### マッピング定義

```mapping.xml
<beanio xmlns="http://www.beanio.org/2012/03"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">

    <stream name="employeeFile" format="csv" >
        <parser>
            <property name="delimiter" value="," />
        </parser>
        <record name="employee" class="example.Employee" >
            <field name="firstName" />
            <field name="lastName" />
            <field name="salary" />
            <field name="hireDate" format="yyyyMMdd" />
            <field name="title" />
        </record>
    </stream>
</beanio>
```

fieldの定義順が対象データの順番と対応している。
デフォルトで区切り文字がカンマなので、この場合parserタグは無くてもいい。
区切り文字を変えたい場合はvalueの値を変更して下さい。

これで準備OK。実際の変換処理を書いてみる。

```BeanReaderExample.java
package example;

import org.beanio.BeanReader;
import org.beanio.StreamFactory;
import java.io.File;

public class BeanReaderExample {
    public static void main(String[] args) {
        // マッピング定義を指定して、ファクトリを生成
        StreamFactory factory = StreamFactory.newInstance();
        factory.load("src/main/resources/mapping.xml");
        // ファクトリからBeanReaderを生成
        // 第1引数にマッピング定義のstream名を指定する
        BeanReader reader = factory.createReader("employeeFile", new File("src/main/resources/employee.dat"));
        // BeanReaderを使ってCSVの内容をオブジェクトにセット
        Employee employee;
        while ((employee = (Employee) reader.read()) != null) {
            System.out.println("FirstName : " + employee.getFirstName());
            System.out.println("LastName  : " + employee.getLastName());
            System.out.println("Salary    : " + employee.getSalary());
            System.out.println("HireDate  : " + employee.getHireDate());
            System.out.println("Title     : " + employee.getTitle());
            System.out.println();
        }
        reader.close();
    }
}
```

実行すると、出力結果は以下のようになる。

```
FirstName : Joe
LastName  : Smith
Salary    : 11000000
HireDate  : Thu Oct 01 00:00:00 JST 2009
Title     : Developer

FirstName : Jane
LastName  : Doe
Salary    : 12000000
HireDate  : Tue Jan 15 00:00:00 JST 2008
Title     : Architect

FirstName : Jon
LastName  : Anderson
Salary    : 6000000
HireDate  : Thu Mar 18 00:00:00 JST 2010
Title     : Manager
```

マッピングできてますね。

# 固定長データ→オブジェクト
#### 固定長データ

```employee.dat
Joe       Smith     01100000020091001Developer
Jane      Doe       01200000020080115Architect
Jon       Anderson  00600000020100318Manager
```

データ長の定義は、
名前=10桁, 姓=10桁, 年収=9桁, 雇用日=8桁, 肩書き=可変長
としています。

固定長と言いつつ、末尾だけは可変長です。
マッピングするクラス（Employee.java）はCSVの時と同じ。

マッピング定義は固定長用に変更する必要があります。

#### マッピング定義

```mapping.xml
<beanio xmlns="http://www.beanio.org/2012/03"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">

    <stream name="employeeFile" format="fixedlength" >
        <record name="employee" class="example.Employee" >
            <field name="firstName" length="10" />
            <field name="lastName" length="10" />
            <field name="salary" length="9" />
            <field name="hireDate" length="8" format="yyyyMMdd" />
            <field name="title" length="unbounded" />
        </record>
    </stream>
</beanio>
```

streamタグのformatを"csv"から"fixedlength"に変更し、fieldタグにlengthを追加。
末尾のみ可変長にできるので、"unbounded"を指定しています。

実際の変換処理（BeanReaderExample.java）と出力結果はCSVの時と同じ。

# その他
今回はCSV、固定長データ→オブジェクトへのマッピングのみでしたが、XMLのマッピングも当然可能です。
ただ、XMLについてはJAXBとかあるし、BeanIO使う利点が分かっていないので、扱っていません。

また、オブジェクト→CSV等への変換も可能です。気が向いたら後日まとめるかも。