• ベストアンサー

巨大なテキストファイル(可変長)を効率よく読込む方法は?

PROMETHEUSの回答

回答No.2

 レコードサイズが今度余り増えないようなら一気に読み込んでしまっても いいのですが、そうでないのであれば、1MB~数MBくらいのバッファに 一度途中まで読み込み、1文字ずつ解析をします。  1回の読み込みではまだファイルにデータが残っていることが多く、 その場合メモリにある最後の行のレコードも途中である可能性もあるので そこの繋ぎ部分は注意して作る必要がありますが、この方法なら それほどファイル読み込みも負荷にはならない可能性が高いですし、 メモリ的に大丈夫でしょう。  で、1行毎の解析ですが、まず分割という処理の必要性が疑問です。  頭から解析し、1つ1つの","で区切られた文字を見て、改行があればそこで1レコード終了になります。  なので、明示的に分割して何かするという処理は要らないです。 >この場合の改行コードは16進表記で「0d0a」ですよね  0x0aだけかもしれませんし、0x0dだけかもしれません。  0x0d/0x0aと連続で来ることを期待して作るとバグを生むかもしれません。 >前回の出現位置から今回の出現位置までをbufにCOPYする。  ファイルからメモリに読み込んだ段階でそこにテキストがあるので これは要りません。(ASCII->UNICODE変換など変換があるなら別ですが)

Han1344
質問者

お礼

PROMETHEUSさん、ありがとうございました。 >で、1行毎の解析ですが、まず分割という処理の必要性が疑問です。 これは、単純に今のプログラム(CSVを分解してデータ処理を行う)がそのまま利用できる、というだけの理由です。 なるほど、頭からCSVを分割してしまう発想はありませんでした。 > 0x0aだけかもしれませんし、0x0dだけかもしれません。 > 0x0d/0x0aと連続で来ることを期待して作るとバグを生むかもしれません。 そうなんですか、Windous系の場合(今はNTFSですが)すべて0x0d/0x0aと連続で来ると思っていました。 ちょっと厄介ですね。 >その場合メモリにある最後の行のレコードも途中である可能性もあるので >そこの繋ぎ部分は注意して作る必要がありますが、 これは漠然とそんなことも考えていました。 やはり自分で何とかしないといけないのですね。 やはりスピードを上げるとなると、厄介なことが多いですね。

関連するQ&A

  • ファイルを読み込むプログラムについて

    下のプログラムで分からない所がありますので、教えて頂ければと思います。宜しくお願い致します。 text = fgets(buf,256,fp);はfpのファイルから一行を読み込んでbufに格納するという処理ということは分かります。でも、while文内なので次にこの処理をする時に今度は、2行目(下の段)を読み込むはずですが、プログラム中のどこに2行目に移動させる処理があるのか分かりません。 予想ですが、text = fgets(buf,256,fp);の中にそのような意味の処理が含まれているのでしょうか? どなたかご教授お願い致します。 #include <stdio.h> int main(void) { FILE *fp; char buf[256]; char *text; char flname[256]; printf("ファイル名:"); gets(flname); fp = fopen(flname,"r"); do{ text = fgets(buf,256,fp); if(text != NULL){ printf("%s",text); } }while(text != NULL); fclose(fp); return(0); }

  • ファイルから読み込んだデータを構造体に格納できますか?

    1レコード19バイトのファイルを 読み込む処理を行っています。 地区名10バイト 県名8バイト 改行1バイト このデータをdouken(構造体)に格納したいのですが >while (fgets(dou,19,fp) != NULL){ で、エラーになってしまいます。 どのようにしたら ファイルから読み込んだデータを 構造体に格納できますか? #include<stdio.h> #include <stdlib.h> struct douken { char tiku[10]; char ken[8]; } main(void){ FILE *fp; struct douken dou[100]; int i; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } while (fgets(dou,19,fp) != NULL){ ・ ・ ・

  • どうやってフローチャートを書きますか

    #include<stdio.h>   void main()   {   FILE*fp;   char buf[128];   char *rc;   char fname[20];   do{   printf("file name>>>");   scanf("%s",fname);   fp=fopen(fname,"r");   if=(fp==NULL) printf("File Open Err¥n");   }while(fp==NULL);   rc=fgets(buf,128,fp);   while(rc!=NULL){    printf("%s",buf);    rc=fgets(buf,123,fp);    }    fclose(fp);    }

  • c言語  2つのファイルを行ごとに読み込むプログラミング

    c言語  2つのファイルを行ごとに読み込むプログラミング 0.txt と 1.txt という2つのテキストフォルダがあり 0.txt の中身は a a b b 1.txt の中身は c c d d というものとします。 これら2つのフォルダを読み込むとき まず1つのフォルダの1行目(a a)を表示し 他方の1行目(c c) 2行目(d d)を表示させて 続いて1つのフォルダの2行目(b b)を表示し 他方の1行目(c c) 2行目(d d)を表示させたいのです。 つまり実行結果が a a c c a a d d b b  ←理想の実行結果です c c b b d d となるようにしたいのですが #include <stdio.h> #include <stdlib.h> #define STR_MAX 256 int main(void) { FILE *fp, *fp2; int i, j, k; char buf[STR_MAX]; char buf2[STR_MAX]; fp = fopen("0.txt", "r"); fp2 = fopen("1.txt", "r"); if (fp == NULL && fp2 == NULL){ printf("\n"); } while(fgets(buf, STR_MAX, fp) != NULL){ while(fgets(buf2, STR_MAX, fp2) != NULL){ printf("%s%s", buf,buf2); } printf("\n"); } fclose(fp); fclose(fp2); return 0; } このプログラミングの実行結果は a a c c a a d d となり、0.txtの2行目(b b)は表示されません。 おそらく while 文 を2重にすることで 不具合が起きているのだと思うのですが 色々と調べた結果、これ以外に プログラミングが思いつきません。 私の理想の実行結果にするためには どこを訂正させると良いのでしょうか? 恐れ入りますが ご回答 どうかよろしくお願いいたします。

  • ファイルを読み込んで条件式を満たさない

    ファイルを読み込んで一部の文字列が来たら別のファイルの文字列を書き込んでもらうプログラムを作ろうとしたのですが、何故かifを使って条件分岐を試みたところ分岐してくれません。 どのようにしたら分岐しますか? 出来ればソースもお願いします。 ---ソースの内容--- #include <stdio.h> #include <string.h> void main(void){ FILE *fp,*fp2; char buf[100],buf2[100]; fp=fopen("yasa.txt","r+"); while( fgets( buf, 100, fp ) != NULL ){ if(strcmp(buf,"じゃがいも")==0){ fp2=fopen("kuda.txt","r+"); while( fgets( buf2, 100, fp2 ) != NULL ){ printf("%s",buf2); } fclose(fp2); } else{ printf("%s",buf); } } fclose(fp); } ---ソースここまで--- ---yasa.txtの内容--- きゃべつ にんじん じゃがいも だいこん セロリ ---yasa.txtここまで--- ---kuda.txtの内容--- もも オレンジ みかん ぶどう ---kuda.txtここまで---

  • ファイルの入出力に関する質問

    CSVファイルを読み込んで、処理をするプログラムを書いています。 しかし、うまくいきません。 CSVファイルは 単語1,数値データ 単語2,数値データ のようになっており、 これをsの配列に格納したいと思っています。 プログラムは以下の通りなんですが。。。 strtokはhttp://www9.plala.or.jp/sgwr-t/lib/strtok.html を参考にしました。 どなたかおしえていただけないでしょうか? #include<stdio.h> #include <string.h> int main(void) { FILE *fp; char s[1000][1000]; char tp[256]; int i=0; if((fp=fopen("in.csv","r"))==NULL){ printf("ファイルオープンできませんよ\n"); exit(1); } while(fgets(tp,256,fp)!=NULL){ tp=strtok(fp,","); puts(s[i][0]=tp); while (tp != NULL ) { tp = strtok(NULL,","); if (tp= NULL ){ puts(s[i][1]=tp); }}i++; } return(0); }

  • 同時にファイル読み込み 書き込み

    現在、ヒストグラムのプログラムを作成しています。 まず0~255の1000個の乱数ファイルdata.txtを読み込み、 ヒストグラムは出来たのですが、 エクセルでグラフを作りたいので、 data1.txtに書き込みたいので、下のソースでやってみましたが、 0~255のカウントが全部0になってしまします。 fp = fopen("data1.txt","w");が無ければ正常に処理されます。 どうか教えてください。よろしくお願いします。 #include <stdio.h> #define BUF 10 #define MAX 256 void count(FILE *fp , int* counter); int main(void) { FILE *fp; fp = fopen("data.txt","r"); fp = fopen("data1.txt","w"); int counter[MAX]; int i; for(i=0 ; i<MAX ; i++) { counter[i] = 0; } count(fp , counter); for(i=0 ; i<MAX ; i++) { printf("%d %d\n" , i, counter[i]); } fclose(fp); return 0; } void count(FILE* p_file , int* counter) { char buf[BUF]; while (fgets(buf , BUF , p_file) != NULL) { int n; sscanf(buf , "%d" , &n); counter[n]++; } }

  • ファイル

    ファイルを読み込み単語ごとに表示するプログラムです。 例 ファイル データ 形式 歴史・・ のように単語の後には空白がありますファイルです FILE *fp; char buf[1000]; char buf_word[1000]; char *str; char *bufstr; if((fp = fopen("test.txt","r")) == NULL){ printf("error!"); return 0; } while(fgets(buf,1000,fp) !=NULL){ str = buf; while(*str !='\0'){ strbuf = buf_word; if(*str ==' '){ printf("%s",buf_word); } else{ *strbuf++ = *str++; } } } とプログラムしてみましたが*strの値がどうもおかしく 最初が "フ" じゃなく"・"になってます。 最初の単語がG11とかなら"G"になっていますが・・ 教えて下さい。

  • fgetsで2行目から文字化け

    fgetsでファイルを一行ずつ読み込みたいのですが、二行目以降が文字化けしてしまいます。 ******* ソース ******* #include <windows.h> #include <stdio.h> FILE *fp; if ((fp = fopen("textlist.txt", "r")) == NULL){ MessageBox(NULL, TEXT("ファイルを開けません"), NULL, NULL); exit (1); } while (1) { TCHAR buf[128] = {0}; if (fgets(buf, sizeof(buf), fp) == NULL) break; MessageBox(NULL,buf,NULL,NULL); } fclose(fp); ***** textlist.txt ***** あいうえお かきくけこ さしすせそ メッセージボックスの一回目は正しく"あいうえお"と表示されますが、二回目・三回目は文字化けしています。 最終的に一行ずつ分けて配列に入れたいので、fgetsで出来たらと思っています。 よろしくお願いします。

  • 配列のメモリの確保

    先日メモリについてご質問させていただいたものですが、 今ファイルから読み込んだ文字列を配列に格納する作業を行なっています。 今は char buf[1000]; FILE fp; if((fp=fopen("○○.txt","r")) ==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) != NULL){ としてファイルを一行ずつ読み込んでその後単語ごとに配列に組み込みます このときファイルの文字列を格納する配列はbuf[1000]ですが このメモリでは足りないかもしれませんし多すぎるかもしれません。 足りない場合はエラーになるし多すぎる場合はメモリの無駄ですよね。 このような場合はメモリを取り直すべきなのでしょうか?その場合 どのような方法がありますか?調べてもint型の領域確保とかそういうのはあるんですがファイルから読み込んだ文字列の領域確保とかは見つからなかったので教えて下さい。