目次> 第14章> 14.3 TOPUPPREVNEXT

14.3 CSVファイルの読み込み

14.2 節の【例4】で紹介した雛形では、1行単位に読み込み、行単位に処理をしました。 1行単位に読み込んだものが、コンマで区切られていると想定し、 コンマで区切られた文字列を読むプログラムにしましょう。

各行のデータが、コンマで区切られているファイルを CSV (Comma Separated Values) と呼びます。 行をレコード、コンマで区切られた部分をフィールドといいます。

CSVファイルの例
例(1)例(2)
10220123,阿部 明子,40,55,C
10220135,加藤 勝男,43,89,B
10420082,佐藤 聡,30,0,D
30130273,田中 玉緒,100,87,A
-,中村 奈々,82,65,B
99420321,羽田 花子,41,63,C
青木一郎,東京都港区,03-3333-4444
石井次郎,神奈川県藤沢市,0462-99-8888
上田三四郎,茨城県古河市,0280-55-6666
江本吾朗,三重県津市,059-224-9999

データを区切る文字をセパレータとかデリミタといいます。 セパレータには通常コンマが用いられますが、データにコンマが含まれる場合など、 タブや空白が用いられる場合もあります。 文字列を引用符(")で括る場合もあります。

CSVであれば、1行分を java.util.StringTokenizer クラスに渡し、 nextToken メソッドを用いるとデリミタまでのデータが得られます。 データの個数分だけ nextToken を繰り返し呼び出します。 データの個数がわからない場合は、 hasMoreToken を参照すれば、 データの有無が調べられます。 この感覚は、Iterator インターフェースの hasNextnext に似ています。
nextToken メソッドを呼び出すと文字列が得られるので、 そのまま文字列として使用するか、 Integer.parseIntDouble.parseDouble などで 必要なデータ変換を行います。

StringTokenizer はデリミタが連続して現れると、 1つのデリミタとみなします。空白をデリミタとした場合などは便利ですが、 CSVのフィールドが空になって、デリミタが連続するとフィールドの位置がずれてしまいます。

J2SE 5.0 以降は、StringTokenizer の代わりに、 String クラスの split メソッドの使用が奨励されています。 【例3】【例4】
逆に、split メソッドでは連続したデリミタを1つのデリミタとする工夫が必要です。 【例6】

【例1】

上記のファイル例(2)を読み、住所・名前の順に表示します。

プログラム CsvDemo1.java

実行結果
CsvDemo1-1.gif

データ・ファイル phone.txt
コマンドラインのパラメータにファイル名を指定できるようにしてあります。 指定がない場合には、phone.txt を仮定します。

【例2】

上記ファイル例(1)の第3フィールドを「点数」とみなして、合計と平均を計算します。

プログラム CsvDemo2.java

実行結果
CsvDemo2-1.gif

データ・ファイル exam.txt
ファイル名の指定がない場合には、exam.txt から読むようになっています。

【例3】

J2SE 5.0 では正規表現が導入され、 String クラスに、文字列を正規表現で区切るメソッドが追加されました。

たとえば、上記【例2】で、

String[] field = line.split(",");
とすると、文字列 line のコンマで区切られた文字列が、 field[0]field[1]field[2]... に分解されます。

プログラム CsvDemo2T.java

実行結果は変わりません。
CsvDemo2T-1.gif

CsvDemo2T.java を実行した時の様子を アニメーションにしてみました。 黒と青の部分が、メモリ内に作られるモノのイメージです。赤は補足説明です。
代入を繰り返し、参照できないオブジェクトがメモリ上に残りますが、 javaのシステムが適宜回収し、メモリを再利用します。この処理をガーベージ・コレクションといいます。

【例4】

データ処理には、Microsoft Excel がよく使われます。 Excel で作成したデータを読んだり、 Excel で入力可能なデータを作成する例を掲げます。

まず、データの作成をしましょう。 Microsoft Excel 2003 でデータを作成し、

excel.gif
CSV形式で出力します。
../java/io/excel2.gif
以下のようなダイアログが表示されますが、「OK」「はい」と答えて保存します。 excel3.gif excel4.gif
カレントディレクトリに record.csv という名前で保存したとしましょう。 エディタで中身をのぞくと次のようになっています。
../java/io/excel5.gif
青い下向き矢印は改行を、[EOF]はファイルの終わりを示しています。

空のフィールドがありますから、【例3】のプログラムを修正してこのファイルを読んでみましょう。 変更点は、

プログラム CsvDemo2Texcel.java

実行結果は変わりません。
CsvDemo2Texcel-1.gif

【例5】

Excel のデータにコンマがある場合には、 「ファイル」→「名前をつけて保存」から、 「ファイルの種類」で「テキスト(タブ区切り)(*.txt)」を選択し、 コンマの代わりにタブでフィールドを区切って出力します。
../java/io/excel6.gif     ../java/io/excel7.gif
コンマの含まれるフィールドは、引用符でくくられますから、 という処理が必要になります。

上図の最後の行は、式の計算値が出力される様子を確認したものです。 1 と 2 は数字ですが、3が表示されているセル(C8)には「 =A8+B8 」という式が入っています。

プログラム CsvDemo7Texcel.java

実行結果
CsvDemo7Texcel-1.gif

入力ファイル csvdata.txt

【例6】

デリミタに空白を採用する場合は、複数の空白が連続しても1つのデリミタとみなすのが普通です。 J2SE 5.0split メソッドを使用する場合には、 正規表現(regular expression) を用いて、「連続した空白」を表現します。

プログラム CsvDemo8T.java

実行結果
CsvDemo8T-1.gif

Javaの正規表現については、 java.util.regex.Pattern を参考にしてください。 文字列内にエスケープ文字(\)を書く場合には、\\ とすることに注意してください。


更新日:2006-03-10 TOPUPPREVNEXT