JavaでCSVを扱う

JavaCSV出力するのに便利なのはないかなと調べていたらSuper CSVなるものを発見。

http://supercsv.sourceforge.net/

Stringの配列を渡したらそれをCSVにしてくれるっていうのはよくあるんだけど、これは、JavaBeansやMapを渡してCSVを書き出してくれるので非常に便利。
CSVを読み込みBeanに入れるには以下のようにするらしいが、めちゃはまってしまった。
まず一つは、以下のライブラリに依存しているようなのでこれをクラスパスに追加しておく。

そして、なぞなのが以下のコードのヘッダの指定をしている部分。

// CSVの1レコードを表すJavaBeans
public class User {
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}	
}

public class CsvTester {
	final static CellProcessor[] processors = new CellProcessor[] {
			null, new ParseInt()
		};
	public static void main(String[] args) throws Exception {
		read();
		
	}
	
	public static void read() throws Exception {
		ICsvBeanReader reader =
			new CsvBeanReader(new FileReader("d:/users.csv"),
			CsvPreference.EXCEL_PREFERENCE);
		
//		String[] header = reader.getCSVHeader(true);
//		for (int i = 0; i < header.length; i++) {
//			System.out.println(header[i]);
//		}
		String[] header = {"name", "age"};
		// 1行目のヘッダを読み飛ばす
		reader.getCSVHeader(true);

		try {
			User user;
			while ((user = reader.read(User.class, header, processors)) != null) {
				System.out.println(user.getName() + ":" + user.getAge());
			}
		} finally {
			reader.close();
		}
		
	}
}

上記コードで使用しているuser.csvの内容は以下の通り

name,age
suzuki, 20
山田, 30

CSVのヘッダ行は通常以下のコードで取得される。

String[] header = reader.getCSVHeader(true);

そして、ここでheaderは["name", "age"]というような内容になっているはずなので、これをICsvBeanReader#readメソッドの2つ目の引数にいれてやるらしいのだけど、これだとうまく行かない。そこで上記コードのようにヘッダの配列を手で作ってみる。

String[] header = {"name", "age"};
// 1行目のヘッダを読み飛ばす
reader.getCSVHeader(true);

getCsVHeaderでは、CSVの1行目を取得しStringの配列にして返している。そして次にICsvBeanReader#readするときには2行目から読み込まれるという感じ。なので、headerは手で作って1行進めるためだけにgetCsVHeaderを実行してるんだけど。
「String[] header = reader.getCSVHeader(true);」これと何が違うの??こいつ(最初のコードのコメント部分)を有効にして実行すると以下のようなエラーになる。

name
age
java.lang.NoSuchMethodException: User.set&#65279;name(java.lang.String)
	at java.lang.Class.getMethod(Class.java:1605)
	at org.supercsv.util.MethodCache.inspectClassForSetMethods(Unknown Source)
	at org.supercsv.util.MethodCache.getSetMethod(Unknown Source)
	at org.supercsv.io.CsvBeanReader.fillObject(Unknown Source)
	at org.supercsv.io.CsvBeanReader.read(Unknown Source)

getCSVHeaderでname, ageという値は取れてる。とよく見ると、「User.setname」ってなに。nameの前になんかあるし。こいつのせいかー。getCSVHeaderのなかで、なんか、おきてるの?
もうだめぽ疲れた。続きはまた来週・・・。

追記

コードをコピーして日記に貼り付けたら「&#65279;」という文字になってた(貼り付けた時点ではスペースが開いていたが、これがはいっていたらしい)そして、調べてみるとBOMというものらいしい。こいつがファイルの先頭に入ってたからダメだったぽい。
UTF-8 - Wikipedia
http://bearmini.net/blog/View.aspx?bid=1&aid=144
サービス終了のお知らせ

追記2

やはり、BOMが入っていたらしい。これを取り除いて(TeraPadだと、文字コードUTF-8Nで保存する)実行すればうまくいきました。