- PR -

javaのCSVファイルの読み込み

投稿者投稿内容
バジオ
会議室デビュー日: 2004/01/20
投稿数: 3
投稿日時: 2004-01-20 23:40
初めまして、今回初めて応募の学生なのですが、プログラムでjavaでCSVファイルを読み込みはどのようなプログラムを組んだら良いのでしょうか?
ゴゴミル
会議室デビュー日: 2004/01/15
投稿数: 7
投稿日時: 2004-01-21 00:27
え〜と、こんな感じでしょうか?
もうちょっとどんな風に動かしたいかがわかればそれなりには作れますが・・・。
実際に動かしてないんで、なんともいえませんが・・・。

また、java.io.FileInputStream,java.io.FileReaderなどそこらへんと、
java.util.StringTokenizerのAPIを参考にするのがよろしいかと。

public final class CSVReader
{
  //CSVファイル列情報
  private static final String[] FIELD_NAME = { "NAME", "ADDRESS", "EMAIL" };

  /**
   * CSVファイル読み込み.<br/>
   *
   * @param fileName
   * @return
   */
  public ArrayList read(String fileName)
  {
    //CSVファイルの全行情報リスト
    ArrayList csvData = new ArrayList();

    BufferedReader reader = null;
    try
    {
      reader = new BufferedReader(new FileReader(new File(fileName)));

      String str = null;
      StringTokenizer st = null;

      //一行ずつ読み込み
      while ((str = reader.readLine()) != null)
      {
        //カンマ区切りで読み込む
        //あまりよくない方法かも・・・
        st = new StringTokenizer(str, ",");

        //作成された列情報マップをリストに格納
        csvData.add(this.createBean2CSV(st));
      }
    }
    catch (FileNotFoundException e)
    {
      //ファイルが見つからなかった場合の例外処理
    }
    catch (IOException e)
{
      //I/O例外処理
    }
    finally
    {
      try
      {
        if (reader != null)
          reader.close();
      }
      catch (IOException e)
      {
        //例外処理
      }
    }
    return csvData;
  }

  /**
   * 行文字列から、列情報作成.<br/>
   *
   * @param line
   * @return
   */
  private HashMap createBean2CSV(StringTokenizer line)
  {
    //CSVファイルが必ずある固定の列を持つならこっちかな?
    //HashMap map = new HashMap(FIELD_NAME.length);

    HashMap map = new HashMap();

    //i < FIELD_NAME.lengthは、FIELD_NAMEよりも列情報が多い場合のため
    //の処理。
    //フィールド名を保持しなくていいorクラス作成するならいらない処理です
    for (int i = 0; line.hasMoreElements() && i < FIELD_NAME.length; i++)
    {
      //列名とその値をマップで保持
      //普通はマップでなくてクラスをつくるかなぁ〜
      map.put(FIELD_NAME[i], line.nextElement());
    }
    return map;
  }
}


[ メッセージ編集済み 編集者: ゴゴミル 編集日時 2004-01-21 00:31 ]

[ メッセージ編集済み 編集者: ゴゴミル 編集日時 2004-01-21 00:37 ]
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-01-21 00:31
はじめまして。勉強がんばってください。
ただ、質問からは何がわからないのかわからないので、もう少し詳しく説明してください。
勉強するのであれば答えをみてもしょうがないですから。

プログラミングをしたことはありますか?

あるのならいろいろポイントがわかると思います。ファイルの読み込み、CSVのパース等。そのうち何がわからないかを切り分け、それぞれ別スレッドとして質問してみましょう。

プログラミングをしたことがない、まったく見当がつかないのであればまずいきなり目的の物ではなく順を追ってできるところからやりましょう。
1)HelloWorld
HelloWorld と画面に表示するだけのプログラム。
2)type/cat
ファイル内容をそのまま画面に表示する。java.io.* のパッケージの使い方を覚えます。
3)CSV のパース
カンマ区切りで文字列を切り分けます。StringTokenizer などの使い方を覚えます。
1カラム中にカンマやダブルクォーテーションを含めるのを容認するとかなり面倒です。
4)目的のプログラム

といった順序でしょうか。どこが出来そうですか?どこが出来なさそうですか?

[ メッセージ編集済み 編集者: インギ 編集日時 2004-01-21 00:31 ]
バジオ
会議室デビュー日: 2004/01/20
投稿数: 3
投稿日時: 2004-01-21 00:54
まだプログラミング(学校に入って)を初めて1週間も経っていません。
インギさんの(2)あたりぐらいでわからなくなっています。
ゴゴミルさんプログラム有難うございます。
えっと問題が、CSVファイル(個人データ:データ数は何件かわからない数)をjavaに読み込みの確認と構造体にデータを格納してからデータの表示すると言う問題です。

まだまだ、青っこいので変な質問投稿ですみませんが宜しくお願いします。
でゅうく
大ベテラン
会議室デビュー日: 2003/11/30
投稿数: 129
投稿日時: 2004-01-21 11:10
Javaの入出力なら詳しく解説しているサイトが沢山あるので検索してみる事をお奨めします。

CSVの解析についてですが、空要素を認めるような仕様のCSVですとStringTokenizerでの解析では少々やっかいです。
以下のコードでは空要素(789と"abc"の間)を認識してくれません。
コード:
String data = "123,456,789,,abc,def";
StringTokenizer tokenizer = new StringTokenizer(data,",");
while (tokenizer.hasMoreTokens()) {
	System.out.println(tokenizer.nextToken());
}


この場合はStringTokenizerのコンストラクタでデリミタ(この場合はカンマ)もトークンとして返すように指定しておいて、取得できたトークンがデリミタかどうか検査しながら制御するはめになってしまいます。
最後の要素が空要素だった場合には、StringTokenizerのトークンが無いにもかかわらずデータを作成することになります。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-01-21 11:26
unibon です。こんにちわ。

引用:

でゅうくさんの書き込み (2004-01-21 11:10) より:
CSVの解析についてですが、空要素を認めるような仕様のCSVですとStringTokenizerでの解析では少々やっかいです。
以下のコードでは空要素(789と"abc"の間)を認識してくれません。


こういう仕様っていやらしいですよね。ちなみに StringTokenizer の javadoc コメントで使っている例文は "this is a test" であり、トークンがコンマではなく空白なのがミソです。C 言語の時も string.h の strtok が使いにくかった記憶があります。
StringTokenizer はいっさい使わずに自前で java.lang.String.indexOf などを使って解析するメソッドを作ってしまったほうが良いような気がします。ただ、標準ではなくなってしまうのが難点ですが、仕様が分かりにくい標準を使うよりはマシかもしれません。


#あとで以下の補足を追加。
私が書いた『こういう仕様っていやらしいですよね。』の「仕様」は、CSV の仕様ではなく StringTokenizer の仕様を指してます。

[ メッセージ編集済み 編集者: unibon 編集日時 2004-01-21 11:28 ]
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-01-21 12:02
CSVファイルの解析を行うという場合、Microsoft Excelが出力するCSV形式ファイル
のフォーマットをサポートするのが普通でしょうね。
その場合、要素自体が改行コードやカンマを含む場合、ダブルクォーテーションを含
む場合を想定する場合などに対応する必要があります。

データ(|がデリミタ)
ABC<改行>DEF|123"456"789|123,456,789|

CSVファイル形式のテキスト
"ABC<改行>DEF","123""456""789","123,456,789",

BufferedReaderでファイルを一行ずつ読み、行ごとにStringインスタンス化→
StringTokenizerで分解、のアプローチは、このようなケースを包括したい場合、
ちょっと無理があると思います。

JavaによるCSVファイルのパース処理は、世界中で再発明が繰り返されている(私も
つい最近JavaCCで作りました^^;)と思いますので、ネットで公開されている
ライブラリを探してみると、どこかにあるかもしれませんね・・・

プログラミングをされる方がPerlなどで正規表現になれているなら、正規表現ライ
ブラリを利用するのも良い手でしょう。JDK1.4以降ではコアAPIに追加になってい
ますし、Apache-Jakartaプロジェクトの正規表現ライブラリを導入する手もあり
ます。

#「CSV形式のサポートがしたい」という用件を聞かされるたびに、「ああ、早くXMLが
#定着してくれないものか」と思う毎日…
#ところで、"CSVファイル"と呼ばれているファイル形式の「標準のフォーマット定義」
#というものは、はたして存在するのでしょうか?
アティ
ベテラン
会議室デビュー日: 2003/08/14
投稿数: 91
お住まい・勤務地: KANAGAWA
投稿日時: 2004-01-21 12:51
ども、アティです。
引用:

シュンさんの書き込み (2004-01-21 12:02) より:
(省略)
JavaによるCSVファイルのパース処理は、世界中で再発明が繰り返されている(私も
つい最近JavaCCで作りました^^;)と思いますので、ネットで公開されている
ライブラリを探してみると、どこかにあるかもしれませんね・・・
(省略)
#「CSV形式のサポートがしたい」という用件を聞かされるたびに、「ああ、早くXMLが
#定着してくれないものか」と思う毎日…
#ところで、"CSVファイル"と呼ばれているファイル形式の「標準のフォーマット定義」
#というものは、はたして存在するのでしょうか?


CSVTokenizerでGoogleで検索をかけると、ライブラリが見つかりますよ。
ついでに、そこからリンクで「標準のフォーマット定義」にも移動できます。

スキルアップ/キャリアアップ(JOB@IT)