- PR -

CSVファイル読込み → データ保持について

投稿者投稿内容
n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2005-10-31 14:36
お世話になっています。 CSVからのデータ取得処理について
ご意見をもらえればと思い書き込みました

現在、CSVファイルから第1、第2、第3列を読込みその値を使って
処理をしています。 その為 1,2,3と固定の為Vectorを3つ用意し
列1,2,3を表していますが、汎用性悪い為、String[][]を使いCSV
全データを取得するようにしたいと考えています。

処理としましては、以下の用にしています。

Stringの2次元配列にする場合、縦、横のサイズがファイル内をみて
みないとわからない為、サイズ指定をどうするべきかで悩んでいます。

その2で記述したメソッドを使い1度ファイル内から件数取得
と考えているのですが、2度もループで中身を見るのは処理が重くなり
そうなので、つくり上よろしくないかと思ったのですが、一般的にはどのよう
にするべきなのでしょうか?

ご意見よろしくお願いします。

コード:

その1
public HashMap getCsvData(String filenm) throws Exception{
Vector vec1 = new Vector();
Vector vec2 = new Vector();
Vector vec3 = new Vector();
try{
InputStreamReader isr = new InputStreamReader(
new FileInputStream(
CMNDefine.CSV_FILE_PATH + filenm
), "MS932"
);
BufferedReader br = new BufferedReader(isr);
String strtoken = "";
int count = 0;

while ((strtoken = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(strtoken, ",");
while (st.hasMoreTokens()) {
// 1行の各要素をタブ区切りで表示
String str = st.nextToken();
if(count == 0) vec1.add(str);
else if(count == 1) vec2.add(str);
else if(count == 2) vec3.add(str);
count++;
}
count = 0;
}

br.close();
isr.close();

HashMap hm = new HashMap();
hm.put("colomn1", vec1);
hm.put("colomn2", vec2);
hm.put("colomn3", vec3);

return hm;
} catch (FileNotFoundException e) {
// Fileオブジェクト生成時の例外捕捉
e.printStackTrace();
SOUMisc.console(e);
throw e;
} catch (IOException e) {
// BufferedReaderオブジェクトのクローズ時の例外捕捉
e.printStackTrace();
SOUMisc.console(e);
throw e;
}
}


コード:

その2
private int getBufColCount(BufferedReader br) throws Exception{
int count = 0;
while( br.readLine() != null){
count++;
}
br.reset();
return count;
}




[ メッセージ編集済み 編集者: n.w 編集日時 2005-10-31 14:37 ]
n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2005-10-31 14:43
調べていて気づいた点があったので追記
whileループ部分について、splitなるメソッドを発見しました。
これにより横のサイズは気にせず、この配列をVecotorあたりへ
addしていき、 検索終了時、VecotorからString[][]へ変換する
ような処理を用いればStringの2次元配列で表をあらわせそうです。

ただ、まだ気持ちの悪いソース感が漂ってしまうのは、やはり
Vecotorから移し変えという1クッション入るからでしょうか・・・

コード:
String strtoken = "";
String[] arrayline;

while ((strtoken = br.readLine()) != null) {
    arrayline = strtoken.split(",");
    out.flush();
}

takashi
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 79
お住まい・勤務地: 東京
投稿日時: 2005-10-31 14:47
こんにちは。

僕がCSVファイルを読み込むときは、だいたいMapを格納したListとして保持します。
1行をMapに格納してListに追加していく感じですね。
コード:
List list = new ArrayList();
while(ファイルを読み込む間){
 Map map = new HashMap();
 map.put("column1", 1列目のカラム);
 map.put("column2", 2列目のカラム);
 map.put("column3", 3列目のカラム);

 list.add(map)
}
return list;


CSVファイルの1行目がカラム名になっている場合は、上記コードのcolumn1,column2,column3をそのカラム名にしたりします。

以上ご参考になれば。
_________________
3年目PG(そろそろSE?)

Σ(゚д゚;) ハッ!?  ベテランに昇格してる・・・
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-10-31 14:59
どもです。がると申します。
ちょっと気になったので。

CSVですが、データの中に,とか改行とかが入りうる可能性
があるかと思うのですが、そのあたりは
・考慮している
・意図的にオミットしている
のいずれかであると捉えてよいのでしょうか?

ちぃと蛇足ではあるのですが、気になったので軽く突っ込みなどを。

mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2005-10-31 15:05
とりあえず、ループが二回発生するのは致し方ないと思いますよ。
全体が分からない場合に、vectorやlist、mapを使うのは正しい方向性かと。

String[][]にこだわる必要がないのなら、
たとえばCSVを、listのlistに突っ込んで保持するクラスを作って、
getdata(x, y)・setdata(x, y)のようなメソッドで1セルずつ扱う、
という方法ではどうでしょうね。
n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2005-10-31 15:08
takashiさん、がるがるさん、ご教授、ご指摘ありがとうございます。

List、HashMapを使いすっきりさせることができました。

また、データ内の,や改行に関しては仕様で入らないという
方向なのでだいじょうぶです。

ただ、ご指摘いただいて気になってしまったのですが、仮に入った場合
どのように対応するべきなのでしょうか?
CSVの,とデータの,だと区別できない(?)からやはり
フォーマットと合いませんみたいな処理で対応とするのでしょうか?

<などのようにデータ内に特定の置換文字(<)とかをいれ置換?
など仕様に合わせてとなってしまいますか?

※ mioさん、投稿がちょうどすれ違ってしまってました、すいません。
確かにsetter、getterを設けるとなおきれいにいけそうですね、
ちょっと手を入れてみます。


[ メッセージ編集済み 編集者: n.w 編集日時 2005-10-31 15:34 ]
takashi
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 79
お住まい・勤務地: 東京
投稿日時: 2005-10-31 15:14
解決なされたようでなによりです。

データの中に,などが含まれていた場合の対応ですが、
こんなものがありました。

http://www.wakhok.ac.jp/~tomoharu/Java/csv/
_________________
3年目PG(そろそろSE?)

Σ(゚д゚;) ハッ!?  ベテランに昇格してる・・・
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2005-10-31 15:32
> String[][]にこだわる必要がないのなら、
(組込みdbを使う)
hsqldb csv
の2語の検索結果でもいいと思います

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