CSVファイルを読み込む際の構造体の使用は効果的か?

このQ&Aのポイント
  • CSVファイルを読み込んで計算する際に、構造体に格納するかどうか悩んでいます。
  • CSVファイルには最大86400行、最大6000列のデータがあります。
  • 構造体を使用するとメモリ使用量が増える可能性がありますが、後ほど拡張する際に便利です。しかし、直接ファイルから読み込む方法のほうが無難かもしれません。
回答を見る
  • ベストアンサー

CSVファイルを読み込んで計算するには、構造体か?

はじめまして。C++プログラミングの質問です。 初心者レベルの質問で申し訳ないのですが、お付き合いください。 CSVファイルを読み込んで、書かれている値を使ってある計算を行う、 ということをしたいのですが、処理方法をどうするか悩んでいます。 CSVファイルに書かれる最大行86400行、最大列6000列です。 また、開発環境はLinuxとなります。 私は「CSVファイルの項目を構造体に格納するクラス」と、「構造体の値を使って計算 するクラス」を考えました。 しかし、構造体ですと最大86400行のものを格納するのは、メモリを食うだけで無駄だという 指摘を受けました。 直接ファイルから値をとってきて、計算クラスに処理させるほうが無難と言われましたが、 「CSVファイルの項目を構造体に格納するクラス=データベース」と考えており、 後々拡張する場合に融通が利くのではないでしょうか。 経験が浅いので、断固たる主張ができないのですが・・・ 構造体に入れることばかり考えていたので、開発のボリュームを抑え、かつ、メモリを食わない 方法を全く思いつきません。 有識者の方へアドバイスを受けたいのですが、 ・大量のデータを読み込む場合、構造体等に格納する方が後ほど助かるか、 それとも、直接ファイル読み込みした方がよいか ・構造体格納のほかに相応しいやり方はないか この2点をメインにお答えいただけないでしょうか。 何か良いやりかたがありましたら教えていただきたいです。 よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • jx-word
  • ベストアンサー率40% (38/94)
回答No.4

No.2です。 先に示したアクセスパターンはアプリケーションの振る舞いを指しています。 CSVファイルに対してどのようなアクセスが必要になるかは、この場合計算クラスがどのような順番でデータを処理するかで決まります。これをアクセスパターンと呼びました。 これに対して最適なアルゴリズムを選択する必要があり、その例を例示しました。 86400行と言うことですので1日分のデータと思われますが、必要な処理とアクセスパターンの例は下記になります。 1日分の各カラムの合計、平均を求める →CSVファイルを先頭から順次読み込み処理する。 1分ごとに過去5分の平均を求める。移動平均。 →多少のランダムアクセスが発生。この分をどこで面倒みるかは検討が必要。 ユーザーからの指定により、任意の条件で検索する。 →ランダムアクセス。条件次第ではDBの使用が必要。 と、アプリケーションの要件でやるべき事が変わってきます。これに応じた最適なアルゴリズムを用意しましょうということです。 CSVファイルを直接1行分返さずに管理クラスを経由することで、この辺りの変動要素を押し込むことができ、拡張された場合に備えます。そんな変動はないということが分かっているならわざわざこんなクラスは必要ではないかも知れません。 で、別の話になりますが、構造体で返すとなると構造体のメンバ数が6000ですね。こちらもあり得ない数字ですので検討が必要そうです。

paburonnn26
質問者

お礼

質問をさせて頂いたのにもかかわらず、お返事が遅れてしまいまして大変申し訳ございません。 詳しいご説明ありがとうございました。 仰るとおり、1日分のデータを扱います。 検討の結果、ランダムアクセスは必要になり、今のところC++のVectorに格納しようかと思っています。 DBを使おうかと思ったのですが、経験がなく、環境的にリスクと考えたためやめました。 C++のVectorをあまり使ったことがないのですが、ランダムアクセスが可能という情報なので、試そうと思います。 ありがとうございました。

その他の回答 (3)

  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.3

Q1:1行ずつ読んで順番に処理できないか(全体を同時に使う必要が無い) YES:→1行ずつ処理する(使用メモリが小さくてすむ) NO:(計算に必要とするデータの順番があらかじめ決められない=ランダムアクセスが必要)→Q2へ Q2:メモリが8GBくらいある and 実行時間の要求がシビア YES:→ファイルを全部メモリに読み込んで処理する(当初想定通り) NO:→データベースにデータを格納して使う データベースはRDBMじゃなくて、1つのキーを指定してアクセスする gdbm とかが速そうで良いんじゃないでしょうか。キーは、struct { int row; int column; } 。 http://archive.linux.or.jp/JM/html/GNU_gdbm/man3/gdbm.3.html

paburonnn26
質問者

お礼

お礼が遅れてしまって申し訳ありません。 せっかく回答して下さったのに、大変失礼致しました。 今回作ろうとしているものは、1行ずつも処理しますし、あらかじめ決められない処理もいたします。 gdbmは知りませんでした。Linuxは初心者ですので、大変参考になりました。ありがとうございます。

  • jx-word
  • ベストアンサー率40% (38/94)
回答No.2

構造体を使ってDB的に扱うという考え方は自体は悪くないと思います。そこまでする必要があるかどうかは別にして。 ただこれを単純に構造体配列としてオンメモリで処理するとなるとGBオーダーのメモリを必要としますので、特別な条件がなければメモリの無駄遣いなのでやめておく方が吉でしょう。 ではどうするかというと、データ管理クラスをこさえてそのクラス経由でファイルにアクセスするのがいいと思います。 基本は行単位のデータの構造体を返すということにして、後はデータアクセスパターンに応じて管理クラスの内容を検討します。 ファイル先頭から全行順番にアクセス →単純に1行読み込み、解析して返す。 ファイル先頭からランダムで行アクセス。但し各行1回ずつ。 →行読み込みの際に各行の位置を覚えておき、これを参考に次の読み込み位置を決定する。 完全なランダムアクセス。 →一旦ファイル全体を走査し、行先頭の位置と長さを覚える。これを基にファイルアクセス。 局所性のあるランダムアクセス。 →上記に加え、簡単なキャッシュ機構を詰め込む。 他にも条件次第でバリエーションはいくらでもありそうですが、ぱっと思い浮かんだのはこんな感じです。 このハイブリッドもありますが、まずは一番簡単な方法を実装し、必要に応じて拡張するのもいいかもしれません。 もっとも管理クラスを作成すると拡張性に優れますが、最初に書いたようにそこまでする必要があるのかどうかの検討は重要です。必要もない拡張性は単なる無駄なコストですので。

paburonnn26
質問者

お礼

詳しいご説明ありがとうございます。 2点質問があります。 上記に示して下さったアクセス方法(4つ)が「管理クラス」の振る舞いのパターンなのでしょうか。 そうだとしたら、計算を行うクラスとは別に、管理クラスはアクセスのパターンを決めるということでしょうか。 すみません、あまりわかっていないため不愉快な気分にさせてしまうかもしれませんが、教えてください。 2点目は、ランダムアクセスする、というメリットは何でしょうか。 下名が知識不足のため発想としてなかったのですが、ランダムにすることによって効率的になるのでしょうか。 詳しいご説明の上、このような質問をしてしまい大変申し訳ないのですが、よろしくお願い致します。

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.1

最大行86400行×最大列6000列×4byteとしても、2GBほど食いますが。 特殊な事情(すべての行および列に対する再帰的な演算をする、例えば津波の波形の変化を求め一番早い到達時刻を計算するとか)があれは別ですが、普通は、メモリをムダに食っているといわれてもしかたないです。 構造体に入れること自体はまちがっていないです。 が、普通は、ファイルを1行ずつ読み込み、その1行分の最大列6000列を構造体へ入れるにとどめます。 計算するといわれている内容によっては(すべての列に対して同じ処理をする場合など)、 1行1列ずつ読み込んで処理する方がいいかもしれません。

paburonnn26
質問者

お礼

早々にコメントありがとうございます。 大変参考になりました。 やりたいことは、「CSV1行から計算に必要な項目を読み込んでパラメータを算出する(3パターンの計算をCSV1行に書き込まれた数値を参照して計算する)」ということです。 全てを構造体に入れてしまうと、やはりメモリを食いますね。

関連するQ&A

  • CSV ⇒ 構造体 ⇒ 文字列配列

    1,あいうえおあいうえお 3,かきくけこ 2,さしすせそさしすせそさしすせそ 3,たちつてと 2,なにぬねの 1,はひふへほはひふへほはひふへほはひふへほ    ・    ・    ・ といったようなCSVファイルがあります。 まずは、それを typedef struct tagSetInf{  int nPattern; // 1or2or3  char szSearch[256]; // 文字列:最大255バイト }SetInf; という構造体に格納していき、そのszSearchの値を nPatternの値に応じて3種類の文字列配列((例)search1,search2,search3)に 格納したいと思っています。 CSVのレコード数は可変です。(たぶん最大数は100くらいだとは思うのですが・・・) 以上の実現方法を教えてください。よろしくお願いいたします。 環境:Win32 API、C/C++。

  • csv読込でVectorに格納した数値を分類したい

    C++について2回目の質問となります。 私、現在CSVファイルの値を取得するコードを書いています。 後々、この値をある計算に使う予定です。 そこで、計算に使う際に使いやすいように分類しながら値を変数に格納したいと考えてます。 CSV1行を分割後にVectorに格納しようと考えています。 このVectorの型に構造体を入れることってできるのでしょうか。 1行を分類したいという意図がありまして、Vector<struct ***>とできないかと思っているのですが、 これは有効なのかがわかりません。 当初は、Vector<int>にするか、Vectorを2次元配列にしてCSVデータを入れていき、計算のときに何番目(何列目)を取り出す、というやりかたにしようと考えていたのですが、分類の仕方は決まりきっているので、分類ごとに構造体を用意し、Vector<struct ***>に順番に入れていく、というやり方を思いつきました。 が、1行を一旦Vector<int>に入れてしまって、あとで必要なところを要素指定したほうがいいのではとまた思い直し、混乱が起こっています。 Vector<struct ***>ということはできるのか、という点、 Vector<int>にして、あとで構造体(変数?)にいれるべきなのか、という点、 または、Vectorに入れるべきではないのか(構造体に入れるならば、リストにすべきか)という点を教えていただけないでしょうか。 わかりにくいようでしたら、随時ご指摘お願いします。 すみません、C++初心者なので、もしかしたらとんでもないことをいっているかもしれませんが、有識者の方、アドバイスをお願いします。

  • ファイルから読みこんで構造体に格納する、

    shohinというファイルに RX-100 odango_tsumeawase 3000という のが 五行ならんでいるのですが、 これを読み込んで struct shohin{ char code[10]: char name[40]; int price; } にファイルから読みこんで構造体配列に 格納したいのですが、構造体配列に格納する やりかたがわかりません。 構造体配列は struct shohin list[];というのを宣言しています。 ファイルから一行読み込んで fprintf()を使おうと思うのですが、 それはできますか? メンバ毎に格納したいのですが、 それがわかりません お願いします。

  • 複数CSVファイルからデータ抽出

    CSVファイルのA列(行は問いません)の文字が転記シートのA列(行は問いません)と一致していたら、転記シートのA列が一致した行の空白に、左から順にCSVファイルのA列が一致した行のF列の値を書き込む。CSVファイルの1行A列を転記シートのF列の値を書き込んだ列の1行目に書き込む。 できれば、書き込んだ値はCSVファイルから消したいです。 コピペでやっていたのですが、ずれていてどうしようもなくなりました。 CSVファイル一つ当たり、4000行ほどあり、ファイルは200弱あります。 プログラムを組んでくださると、ありがたいのですが。 質問というよりお願いになってしまいますが、よろしくお願いします。

  • CSVファイルの取り込みについて

    CSV取り込み方法について 教えていただきたくお願いいたします。 エクセルのマクロ・VBAの組み方について デスクトップ上の000という名前のCSVファイルを、作業しているエクセルファイルのLoadという名前のシートに貼り付けたいと思っています。 CSVファイルはエクセルで開くと1行に11列の項目が展開されています。 貼り付ける項目はこのようになります。 (CSV) →(エクセルのLoadシート) 1列目(A行)→B行へ 2列目   →C行へ 3列目   →D行へ 4列目   →E行へ 5列目   →F行へ 9列目   →G行へ 10列目  →H行へ 11列目  →I行へ (6.7.8列目は使いません) 最後にLoadのシートのA行に”=B&E”とい式を入力したいと思っています。 まだ初心者なので勉強中なのですが、仕事上急遽必要になりましたのでお願いいたします。

  • csvファイルを構造体に読み込みたい

    C言語初心者です。 csvファイルのデータを1行ずつ構造体に読み込みたいのですが、うまくできません。 #define MAX_SIZE 100 char filename[] = ″test.csv"; struct ALL_DATA{ int cnt; char list[10]; char addr[10]; char cmd[10]; char csize[10]; char input[10]; char icmd[10]; char input2[10]; }; for (int lp = 0; lp < 10; lp++){ FILE *fp; struct ALL_DATA ADATA[MAX_SIZE]; // 構造体配列の宣言 if ((fp = fopen(filename, "r")) == NULL){ printf("%s open error !\n", filename); exit(1); } for (fc = 0; fc < MAX_SIZE; fc++) { if (feof(fp)){ break; } else{ fscanf(fp, "%d,%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],\n", &ADATA[fc].cnt, ADATA[fc].list, ADATA[fc].addr,ADATA[fc].cmd,ADATA[fc].csize,ADATA[fc].input,ADATA[fc].icmd,ADATA[fc].input2); } } fclose(fp); while (i < MAX_SIZE){ printf("ADATA[i].cnt -> %d, ADATA[i].list -> %s, ADATA[i].addr -> %s, ADATA[i].cmd -> %s, ADATA[i].csize -> %s, ADATA[i].input -> %s, ADATA[i].icmd -> %s, ADATA[i].input2 -> %s\n",ADATA[fc].cnt, ADATA[fc].list,ADATA[fc].addr,ADATA[fc].cmd,ADATA[fc].csize,ADATA[fc].input,ADATA[fc].icmd,ADATA[fc].input2); i++; } } 読み込みたいcsvデータは 1 test 0x0012 write 0x001 yes 0xabc yes 2 testa 0x00cd read 0x024 0x1a3 のように、「数字、文字列・・・」と並んでいます。 このデータを取り込んで表示させたところ、 最初の数字は問題ないのですが、ADATA[i].addr から値がおかしくなり、 ADATA[i].addr = 0x0012write ADATA[i].cmd = write ADATA[fc].csize = 0x001yes のように、16進数を文字列として構造体に入れるときに、次の文字(英字)まで一緒に含んでしまう現象が出ております。 ネットで調べて、csvファイルから構造体に取り込む方法はいくつか見たのですが、同じようにしている(と思っている)のにうまくいかないため、質問させていただきました。 原因がわかる方がいらっしゃいましたら、アドバイスをよろしくお願いいたします。

  • VisualBasicからcsvファイルを読み込む

    VisualBasicからcsvファイルを以下のようなプログラムで読み込んでいます。 Open ファイルパス For Input Shared As #1 Do Until EOF(1): Input #1, A(i), B(i): i = i + 1: DoEvents: Loop Close #1 n行2列のcsvファイルとn行3列のcsvファイルを読み込んだ時に A(2)にセルB1、B(2)にセルB2の値を代入したいです。 現状だとn行3列のcsvファイルを読み込んだ時に A(2)にはセルA3の値が入ってしまいます。 n行3列の3列目のデータは無視したいです。

  • 複数のcsvファイルを1つのEXCELファイルにマージするVBAを教えてください

    csvファイル数は700~1000個程度でひとつのフォルダに格納されています。 このファイルをEXCEL形式で開くと、1行目にフィールド名(A~Z列で固定)、2行目以降にデータが入っています。行数はファイルにより1~100行程度で変動します。 このファイルを1つのエクセルファイルの同一シートに結合(マージ)するVBAがほしいです。 ここで、(できればですが)EXCELにマージするにあたり、1行目のみフィールドの値、2行目以降にそれぞれのcsvの2行目以降データの値を入れていくようにしたいです。つまり、フィールド名の行が何行も出てくるのを避けたいです。 申し訳ございませんが、ご指導いただけたら幸いです。よろしくお願いします。

  • VB .Netの構造体について

    構造体について教えて下さい。 クラスで構造体を作成しました。 クラスでIniファイルを読み込み、Formのボタンを押した処理の中で構造体を読み込みたいのですが、何をしても空白(Nothing)になります。 クラスの中では格納されたままなのに・・・。 違う場所で構造体を呼んだときは別の処理がいるのでしょうか? それともVB .Netの仕様なのでしょうか?

  • strutsでCSVファイルの取込

    strutsでCSV形式のファイルを取得し、内容を画面に表示するプログラムを作成しています csvファイルの途中で空項目(何も入っていない項目)があると、それ以降ズレて取得されてしまいます。 (違う行になると、また正常に取得できます) 空項目があった場合でも空のまま取得し、それ以降もズレずに取得する方法は無いでしょうか? よろしくお願いします。 ●コーディングの抜粋 String filename = file.getFileName(); InputStream is = file.getInputStream(); InputStreamReader isr = new InputStreamReader(is); while((csvData = ibufr.readLine()) != null){ String data0 = GetArrayToString.getErrElement(csvData,0); String data1 = GetArrayToString.getErrElement(csvData,1); String data2 = GetArrayToString.getErrElement(csvData,2); String data3 = GetArrayToString.getErrElement(csvData,3); String data4 = GetArrayToString.getErrElement(csvData,4); } ●CSVデータ 1行目 → 0,1,2,3,4 2行目 → 0,,2,3,4 ※2行名の2列目が空になっている ●取得結果        data0 data1 data2 data3 data4 1行目 →   0   1   2    3   4 2行目 →   0   2   3    4 ※CSVデータでは、2行2列目の値が空のときに、GetArrayToString.getErrElement()を起動すると、 2行2列目が空なので2行3列目の値を取得していまいます。 それ以降、行が変わるまでズレてしまう。 空の場合、隣の列の値を取得せずに空のまま取得し、それ以降の項目もズレずに取得したいです。 対処方法があればお願いします

    • ベストアンサー
    • Java

専門家に質問してみよう