JavaでCSV形式のファイルを読み書きするJavaTips 〜Javaプログラミング編

» 2004年07月06日 10時00分 公開
[佐藤匡剛@IT]

 表形式のデータを簡単に扱いたいときに、CSV(Comma Separated Values)形式を用いる方法があります。CSVでは、データの各要素をカンマ(「,」)で区切り、改行がそのままデータ行の区切りを表します。CSVデータは、一般に「.csv」という拡張子の付いたテキストファイルとして保存されます。テキストエディタだけでなく、Microsoft Excelなどの表計算ソフトでも読み込むことができ、閲覧や編集が簡単なため、よく利用されます。

 本稿では、CSV形式のデータをJavaで扱うときの基本的な手順を紹介します。サンプルとして、以下のCSVデータを扱います。このデータは、日本の作家の生年/没年を表しています。

writers.csv
宮沢賢治,1896,1933
稲垣足穂,1900,1977
三島由紀夫,1925,1970

解説

 CSVデータの読み込みには、コアAPIのjava.io.BufferedReaderクラスと、java.util.StringTokenizerクラスを併用します(J2SE1.4以降なら、StringTokenizerクラスの代わりに、java.lang.String#split(String)メソッドを用いることもできます)。java.ioパッケージのクラスを用いてファイルの入出力を行い、StringTokenizerクラスによって、カンマ区切りのデータを要素ごとに分割していきます。以下のサンプルプログラムは、読み込んだCSVデータをタブ区切りで標準出力に表示します。

ReadCSV.java
package javatips;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;
 
public class ReadCSV {
 
  public static void main(String[] args) {
    try {
      File csv = new File("writers.csv"); // CSVデータファイル
 
      BufferedReader br = new BufferedReader(new FileReader(csv));
 
      // 最終行まで読み込む
      String line = "";
      while ((line = br.readLine()) != null) {
 
        // 1行をデータの要素に分割
        StringTokenizer st = new StringTokenizer(line, ",");
 
        while (st.hasMoreTokens()) {
          // 1行の各要素をタブ区切りで表示
          System.out.print(st.nextToken() + "\t");
        }
        System.out.println();
      }
      br.close();
 
    } catch (FileNotFoundException e) {
      // Fileオブジェクト生成時の例外捕捉
      e.printStackTrace();
    } catch (IOException e) {
      // BufferedReaderオブジェクトのクローズ時の例外捕捉
      e.printStackTrace();
    }
  }
}

訂正のお知らせ(2009年3月31日)

読者から上記のサンプルコード、「while (br.ready())」について貴重なご指摘をいただき、コードを差し替えさせていただきました。

内容について正確を期せずに混乱を招いた点、読者の皆様におわび申し上げます。


 ファイルからデータを読み込むときは、java.io.BufferedReaderクラスを使うのが基本です。java.io.FileReaderクラスでもデータを読み込むことは可能ですが、バイトごとに読み込みを行うため非効率です。その点、BufferedReaderクラスなら、バッファリングによってまとめて読み込みが行われるため、効率的に処理することができます。

 上のコードを実行すると、次のような結果が得られます。

> javac javatips\ReadCSV.java
> java javatips.ReadCSV
宮沢賢治 1896 1933 
稲垣足穂 1900 1977 
三島由紀夫 1925 1970

 さて、今度はCSVファイルにデータを書き出します。書き出しは、通常のファイルへのデータ出力と同様に、java.io.BufferedWriterクラスを用います。データの要素をカンマで挟んで連結し、ファイルへ書き出すだけです。以下のサンプルプログラムでは、CSVファイルの末尾へデータを1行追加しています。

WriteCSV.java
package javatips;
 
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
 
public class WriteCSV {
 
  public static void main(String[] args) {
    try {
      File csv = new File("writers.csv"); // CSVデータファイル
      // 追記モード
      BufferedWriter bw 
        = new BufferedWriter(new FileWriter(csv, true)); 
      // 新たなデータ行の追加
      bw.write("中上健次" + "," + "1946" + "," + "1992");
      bw.newLine();
      bw.close();
 
    } catch (FileNotFoundException e) {
      // Fileオブジェクト生成時の例外捕捉
      e.printStackTrace();
    } catch (IOException e) {
      // BufferedWriterオブジェクトのクローズ時の例外捕捉
      e.printStackTrace();
    }
  }
}

 ファイルへの書き出しも、読み込みと同様にバッファリングをして書き出す方が効率的なので、書き出しにはjava.io.BufferedWriterクラスを用います。

 このプログラムを実行します。

> javac javatips\WriteCSV.java
> java javatips.WriteCSV

 データの書き出しが行われたwriters.csvは、以下のように変更されます。

writers.csv(データ追記後)
宮沢賢治,1896,1933
稲垣足穂,1900,1977
三島由紀夫,1925,1970
中上健次,1946,1992

注意:CSVデータでは、カンマや改行は特別な意味を持っているため、それらをデータの要素として扱いたいときは、適切にクオートしなくてはなりません(CSVに標準というものはありませんが、例えばExcelでは、カンマや改行を含むデータ要素を「"」で囲み、データ要素に「"」が含まれる場合はそこを「""」と変換します)。ここでは、CSVファイルの最低限の読み書きの説明を目的としているため、そのような高度な処理の部分については、割愛してあります。データの要素にカンマや改行などを含めたい場合は、データのクオートを行わなくてはならないことを覚えておいてください。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。