【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は謹んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.19454

ファイル中のレコード件数取得について
投稿者---You(2005/01/24 21:15:50)


初めてカキコしますがとても困っているのでお願いします。

今、VS.NETのC++でのファイル操作を行おうとしています。

CSVファイルの中のレコード件数を取得したいのですが
探してもレコードセットばかりヒットします。
扱うのはデータベースではないのでこれは使えないと思います。

レコードを1行ずつ読み込んで数える方法もあるのですが
読み込む処理があまり効率的によくないと思い
それよりもファイルの終点の位置から何とかレコード件数を
取得しようと考えた結果が下です。

     FILE *fp;
     long a;

     fp = fopen("ファイルのフルパス\\file.csv", "r");

     if (fp == NULL) {
        //エラーログの出力
        return -1;
     }

     fseek(fp,0L,SEEK_END);

     a = ftell(fp);

     fclose(fp);

これだと終点の位置はバイト数(正確には違いますが)で
読み込めるのですがCSVは可変長で1レコードのバイト数が
決まっていないので

     a / (CSVの1レコードのバイト数)

とはできないのです。
ftellがレコード位置数を表していれば

     a - 1

でファイルのレコード件数を取得できたのですが・・・
そんな標準関数がないかと探したのですがヒットしません・・・。

何かいい方法はないでしょうか?
やはり1行ずつfgetsで行数をカウントしていくしかないんでしょうか?
とても困っているので宜しくお願いいたします。



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:ファイル中のレコード件数取得について 19455 RAPT 2005/01/25 00:27:07


No.19455

Re:ファイル中のレコード件数取得について
投稿者---RAPT(2005/01/25 00:27:07)


STLを使えば簡単。

#include <string>
#include <fstream>

using namespace std;

int main()
{
    size_t line = 0;
    ifstream f("cpptest.cpp");
    string str;

    while( !f.eof() ){
        getline(f, str);
        ++line;
    }
    f.close();
    cout << line << "行" << endl;
    return 0;
}




この投稿にコメントする

削除パスワード

No.19456

Re:ファイル中のレコード件数取得について
投稿者---かずま(2005/01/25 02:36:59)


>    while( !f.eof() ){
>        getline(f, str);
>        ++line;
>    }

これだと、結果が 1 多くなりますよ。なぜだか、説明できますか?
次のようにすればよいでしょう。

    while (getline(f, str)) line++;


さて、行数を数えるだけなら、'\n' を数えれば済むのではないでしょうか?
C で書くと、

#include <stdio.h>

int main(void)
{
    int c, line = 0;
    FILE *fp = fopen("file.csv", "r");
    if (fp == NULL) return 1;

    while ((c = getc(fp)) != EOF)
        if (c == '\n') line++;
    printf("%d\n", line);

    return 0;
}



この投稿にコメントする

削除パスワード

No.19459

Re:ファイル中のレコード件数取得について
投稿者---You(2005/01/25 08:15:39)


お返事ありがとうございます!
なるほど、確かに\nの数でわかりますね。

>> while( !f.eof() ){
>> getline(f, str);
>> ++line;
>> }
>
>これだと、結果が 1 多くなりますよ。なぜだか、説明できますか?
>次のようにすればよいでしょう。

lineのインクルードが実行前処理の++lineになっているからか〜
実行後処理のline++にすればいいんですね!
勉強になります!

\nを数えるのはいいと思うのですが
送られてくるCSVファイルが壊れてる可能性ってどうなんでしょうか?

例えば
先頭行に初めから\nが入っていたり、
最後の行に1つしかないはずの\nが2つ入っていたり・・・
他にも気づかないCSVの例外ってあるんでしょうか?

実務のバッチ処理に使われる1部分のプログラムなんで
そこまで考えなきゃなのかはよくわからないのですが・・・
そこまで考えるなら仕様の把握かな?

なにせ初心者なのでどこまで例外を考えればいいのか
わからないのです。
通常はそんな例外ありえないんですかね?


この投稿にコメントする

削除パスワード

No.19460

Re:ファイル中のレコード件数取得について
投稿者---You(2005/01/25 08:35:02)


追記、
ちなみに行を数える方法と\nを数える方は
どちらの処理が効率がいいんでしょうか?
fgetcは1文字ずつの処理ですよね?
なので1文字ずつ判定する方が処理に時間が
かかるように思えるのですが・・・
どうなんでしょうか?
なるべく処理に時間をかけたくないので
スマートなコードにしたいと思っています。




この投稿にコメントする

削除パスワード

No.19461

Re:ファイル中のレコード件数取得について
投稿者---YuO(2005/01/25 10:27:55)


>lineのインクルードが実行前処理の++lineになっているからか〜
>実行後処理のline++にすればいいんですね!

外れです。

Cのfeofもそうですが,ストリームがEOFになるのは,
読み出し処理を行ったあとです。
つまり,初回のf.eof()は常に偽であり,直後のgetlineの呼び出しによって,
場合によってはEOF状態になります。

この場合,一行もなかったわけですが,++lineされた結果,lineは1になります。


>\nを数えるのはいいと思うのですが
>送られてくるCSVファイルが壊れてる可能性ってどうなんでしょうか?

それをどう扱うかはソフトウェアの仕様次第です。



この投稿にコメントする

削除パスワード

No.19458

Re:ファイル中のレコード件数取得について
投稿者---You(2005/01/25 07:55:30)


さそっくの返事、ありがとうございます!
やっぱり行を数えるしかないのですね・・・
使っているのはC++なのでC++でのご返事ありがとうございます!
自分が作るとC++とCが混じったコードになってしまうので
試してみたいと思います!


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧