• ベストアンサー

バイナリデータ作成したいのですが、fwriteの使用方法を教えてください。

indataというhexで書かれたテキストファイルをバイナリデータに変換したく 以下のようなプログラムを作成しましたが、dataのサイズを大きくすると coreダンプしてしまいます。具体的には7M超くらいから。 入力ファイルサイズはほぼ無限にあり、出力バイナリファイルは20MByteは欲しいです。 どのように改造したら、大きなサイズのバイナリファイルが作成できるでしょうか? 初心者ながら、いろいろ調べてここまで作成したので、根本がおかしいかもしれません。 よろしくお願いいたします。 #include<stdio.h> int main(void) { FILE *FPi, *FPo; char data[5000000]; int getdt,x; FPi=fopen("indata","r"); if ( FPi == NULL ) {return 1;} FPo = fopen("res.bin","wb"); if ( FPo == NULL ) {return 1;} x=0; while (1) { if(fscanf(FPi,"%x" , &getdt) == EOF ) {break; } data[x]=getdt; x++; } fwrite(data, sizeof(data), 1, FPo); fclose(FPo); fclose(FPi); return 0; }

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

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

#2方が適切なアドバイスをされていますので、 そのアドバイスに従い、書き換えると以下のようになります。 char data;として while (1) { if(fscanf(FPi,"%x" , &getdt) == EOF ) {break; } data = getdata; fwrite(&data, sizeof(data), 1, FPo); } 要は、1回のfscanfで1文字が取得できるので、それを直ちに書き込みます。これを、入力ファイルがからになるまで繰り返します。そうすれば、入力ファイルのサイズが、いくら大きくても大丈夫です。

lts107
質問者

お礼

大変有難うございました。 教えていただいた方法で解決いたしました。

その他の回答 (2)

noname#11920
noname#11920
回答No.2

まず、コアダンプの理由から。 dataの宣言がauto(自動変数)になっています。 これではアプリケーションのスタック領域をすぐに使い果たしてしまいます。 このような大きな配列を宣言するときは、static属性をつけます。 static char data[5000000]; (もし動的メモリ割り当てを御存じなら、 配列のかわりにそれを使いましょう。 その場合sizeof(data);などとは出来ないことには 注意してください。) 次にfwrite関数の使いかたですが、 fwrite関数の定義は size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream); となっています。 ptrには書き込むデータへのポインタをあたえます。 第2引数のsizeには1要素あたりの大きさをあたえます。 例えば、書き込む単位が配列全体であれば、 sizeof(data)、int型の整数ならsizeof(int)とします。 第3引数のnには、書き込む要素数をあたえます。 第2引数に指定したサイズのものが幾つ続いているか、という値です。 最後の引数streamには、fopenの戻り値をあたえます。 というわけで、ご質問のソースでは使いかたはあっています。 配列をやめて1バイトずつ、例えばchar c;と宣言されたcを書き込むのなら、 fwrite(&c, sizeof(c), 1, FPo); とするわけです。 ただ、これを5000000回ループするのは止めたほうがいいと思いますが。 因みにfwrite関数の戻り値は書き込んだ要素数です。

lts107
質問者

お礼

大変有難うございました。

  • 50100
  • ベストアンサー率28% (99/351)
回答No.1

data[]という配列サイズを固定にしているため、5Mバイト超えるとオーバーフローしますね。 配列に溜め込む方式を辞めて、1ブロック読み込んだら1ブロック書き出すというようにしましょう。 (ブロックサイズは扱うファイルサイズによって調整すればパフォーマンスを上げることができますが、たとえば1024バイトではいかがでしょう。)

lts107
質問者

補足

早速のアドバイス有難うございます。 ご指摘の通り、"1ブロック読み込んだら1ブロック書きだす"としたいのですが、fwriteの使い方が根本的に分かってないものですから、このようなお粗末な状況となっております。 どうしたら実現できますか? 尚、data[]の中の固定値はいろいろ変えてみたのですが上記あるように7M超えるとCoreダンプします。

関連するQ&A