[java]Super CSV で区切り文字や改行文字を任意に指定する

「で、区切り文字とかどうなってんの?」


はい、ちゃんと用意されています。CsvPreferenceというクラスで指定できます。
次のように第2引数で指定します。

ICsvBeanReader inFile = new CsvBeanReader(new FileReader("./data/foo.csv"), CsvPreference.EXCEL_PREFERENCE);

ICsvMapWriter writer = new CsvMapWriter(new FileWriter("./data/boo.csv"), CsvPreference.EXCEL_PREFERENCE);


CsvPreference.EXCEL_PREFERENCEを使用していますが、予め用意されている定義は全部で4種類。

定数名称 クォート文字 区切り文字(デリミタ) 改行文字
STANDARD_PREFERENCE " , \r\n
EXCEL_PREFERENCE " , \n
EXCEL_NORTH_EUROPE_PREFERENCE " ; \n
NO_COMMENT_PREFERENCE " , \n

何気にEXCEL_PREFERENCEとNO_COMMENT_PREFERENCEは、定義内容が全く同じです。

さて、当然これ以外のパターンについても任意で指定することが可能です。たとえば、クォート文字を'B'、区切り文字を'?'、改行文字列を"\r\n"としたい場合、

CsvPreference preference = new CsvPreference('B', '?', "\r\n");
ICsvBeanReader inFile = new CsvBeanReader(new FileReader("./data/foo.csv"), preference);

ICsvMapWriter writer = new CsvMapWriter(new FileWriter("./data/boo.csv"), preference);

といった要領でCsvPreferenceをインスタンス化し、使用します。

[java]Super CSV による File Read

Super CSVは、CSVファイルをオブジェクトのような感覚で扱うことができる、オープンソースCSVファイル高速アクセスライブラリです。言ってみればO/RマッピングCSVファイル版ですね。
http://supercsv.sourceforge.net/
これが非常に便利そうなのに、何故かサイトに載っているサンプルコードが微妙に不親切なので、簡単に書き換えてみました。


読み込むCSVファイルの内容は次のような感じです。
ファイル名:foo.csv

username, password,   date,        zip,  town
Klaus,    qwexyKiks,  17/1/2007,   1111, New York
Oufu,     bobilop,    10/10/2007,  4555, New York

さて、まずはBeanの定義。このクラスでは、CSVファイルの列要素を定義します。
ファイル名:UserBean.java

package bean;

import java.util.Date;

import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.ParseDate;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.constraint.Unique;
import org.supercsv.cellprocessor.ift.CellProcessor;

/**
 * CSVファイルの要素定義(Bean)
 * @author kazuki.kido
 */
public class UserBean {
    
    /** 各要素フォーマット定義 */
    public static final CellProcessor[] processors = new CellProcessor[] {
            new Unique(new StrMinMax(4, 20)),    // username
            new StrMinMax(7, 35),                // password
            new ParseDate("dd/MM/yyyy"),         // date
            new Optional(new ParseInt()),        // zip
            null                                 // town
    };
    
    /* 各要素の Getter/Setter 定義 */
    
    private String username, password, town;
    private Date date;
    private int zip;

    public String getPassword() { return password; }
    public Date getDate() { return date; }
    public String getTown() { return town; }
    public String getUsername() { return username; }
    public int getZip() { return zip; }
    public void setPassword(String password) { this.password = password; }
    public void setDate(Date date) { this.date = date; }
    public void setTown(String town) { this.town = town; }
    public void setUsername(String username) { this.username = username; }
    public void setZip(int zip) { this.zip = zip; }
}

で、実際に読み込み処理を行うmain実装が↓のようなかんじになります。読み込んだ内容をコンソール出力します。
ファイル名:ReadingObjects.java

package read;

import java.io.FileReader;

import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;

import bean.UserBean;

/**
 * SuperCSVによるCSVファイル読み込み
 * @author kazuki.kido
 */
public class ReadingObjects {
    
    public static void main(String[] args) throws Exception{
        ICsvBeanReader inFile = new CsvBeanReader(
            new FileReader("./data/foo.csv"), CsvPreference.EXCEL_PREFERENCE);
        try {
            final String[] header = inFile.getCSVHeader(true);
            UserBean user = null;
            while((user = inFile.read(UserBean.class, header,
                            UserBean.processors)) != null){
                // 取得要素をコンソールへ出力
                System.out.print("ユーザ名:" + user.getUsername());
                System.out.print(" パスワード:" + user.getPassword());
                System.out.print(" 日付:" + user.getDate());
                System.out.print(" 郵便番号:" + user.getZip());
                System.out.println(" 住所:" + user.getTown());
            }
        } finally {
            inFile.close();
        }
    }
}

で、コンソール出力結果がこんなかんじになります。

ユーザ名:Klaus パスワード:qwexyKiks 日付:Wed Jan 17 00:00:00 JST 2007 郵便番号:1111 住所:New York
ユーザ名:Oufu パスワード:bobilop 日付:Wed Oct 10 00:00:00 JST 2007 郵便番号:4555 住所:New York

Beanを介してCSVファイルの内容を簡単に取得できます。定義に沿ってDate型なんかに自動変換してくれるので、とても楽です。


ちなみにプロジェクト構成は以下の通り。

[java]Super CSV による File Write

では続いてファイル書き込みもやってみましょう。
ファイル名:WritingMaps.java

package write;

import java.io.FileWriter;
import java.util.HashMap;

import org.supercsv.io.CsvMapWriter;
import org.supercsv.io.ICsvMapWriter;
import org.supercsv.prefs.CsvPreference;

/**
 * SuperCSVによるCSVファイル書き込み
 * @author kazuki.kido
 */
class WritingMaps {
    public static void main(String[] args) throws Exception {
        ICsvMapWriter writer = new CsvMapWriter(new FileWriter("./data/boo.csv"), CsvPreference.EXCEL_PREFERENCE);
        try {
            final String[] header = new String[] { "name", "city", "zip" };
            // 1行目データを作成
            final HashMap<String, ? super Object> data1 = new HashMap<String, Object>();
            data1.put(header[0], "Karl");
            data1.put(header[1], "Tent city");
            data1.put(header[2], 5565);
            // 2行目データを作成
            final HashMap<String, ? super Object> data2 = new HashMap<String, Object>();
            data2.put(header[0], "Banjo");
            data2.put(header[1], "River side");
            data2.put(header[2], 5551);
            // ファイルへ出力
            writer.writeHeader(header);
            writer.write(data1, header);
            writer.write(data2, header);
        } finally {
            writer.close();
        }
    }
}

こちらはBeanではなく、Mapを用いています。当然、ICsvBeanWriter, CsvBeanWriterとUserBeanを使えば、Beanによる書き込みも可能です。
[java]CsvBeanReader, CsvBeanWriter, ParseDateを併用するには - Undead mode 忘備録

ファイルへの出力結果は次の通り。
ファイル名:boo.csv

name,city,zip
Karl,Tent city,5565
Banjo,River side,5551

よさげです。