C言語のfopen関数とfseek関数について

このQ&Aのポイント
  • C言語のfopen関数について、バイナリモードでファイルを書き換える方法と既存のファイルを上書きしてしまう問題について解説します。
  • C言語のfseek関数について、ファイルの途中部分を書き換える方法とファイルの全体を知る方法について解説します。
  • C言語のfopen関数とfseek関数を使ってファイルの操作を行う際の注意点について解説します。
回答を見る
  • ベストアンサー

C言語のfopen関数とfseek関数についてお尋ねします。

fopen関数について オープンモードは様々ありますが、既存のファイルをバイナリモードで書き換えるということは出来ないのでしょうか? オープンモードが、「wb」などの場合は既存のデータを上書きしてしまって、内容が消えてしまいます。 かと言って、「ab」で開くと最後から追加されてしまいます。 fseek関数を使って、場所を指定しても言うことを聞いてくれませんでした。 既存のファイルの途中部分を少し書き換えるだけの作業は、出来ないのでしょうか? fseek関数について バイナリモードで開いているときに、ファイルの全体を知りたい時に次のように書いたら間違いなのでしょうか? fseek(FILE *stream, 0, SEEK_END); ftell(FILE *stream); fseekで最後のポジションに移動させて、ftellで最後のカレントポジションを調べるという方法は使えるのでしょうか? 以上2点よろしくお願いします。

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

ftell って long int を返すから, 「long int の範囲を超えてしまうような大きさのファイル」だと絶対に不可能です.

その他の回答 (3)

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.3

・fopen ファイル途中の「上書き」のみ可能で、「挿入」も「部分削除」も不可能です。 ・fseek 出来る場合出来ない場合があるのは#2で言われている通りですが、ファイルサイズを取るなら普通はfstatかstatを使うのでは。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> バイナリモードで開いているときに、ファイルの全体を知りたい時に次のように書いたら間違いなのでしょうか? > fseek(FILE *stream, 0, SEEK_END); > ftell(FILE *stream); 規格上は期待通りの結果が得られることは保証されません。 特定の処理系に限定すれば、うまく動くこともあります(詳しくは処理系のドキュメントを読んでください)。

  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.1

> fopen関数について 「rb+」(もしくは「r+b」)で開けば、fseekで指定した既存のファイル内容を書き換えができます。 > fseek関数について 可能です。SEEK_ENDで末尾に移動してから、ftell すれば、ファイルサイズが得られます。

関連するQ&A

  • バイナリファイルの読み込み(C言語)

    raw(音楽ファイル)データを配列rawに読み込みたいのですが,バイナリファイルの読み込み方がわかりません. サンプルで以下のようなソース(途中略)があるのですが, ・なぜrawの型としてshortを使っているのか ・データ数の半分(file_size = ftell(fp) / 2)しか読み込んでいない ・fgetc(fp) << 8 あたりの意味がわからないので教えて下さい. -------------------------------------------------------- short *raw; if((fp=fopen(argv[1], "rb")) == NULL){ fprintf(stderr, "can't open %s.\n", argv[1]); exit(1); } fseek(fp, 0, SEEK_END); file_size = ftell(fp) / 2; fseek(fp, 0, SEEK_SET); raw = (short *)malloc((size_t)(file_size * sizeof(short))); if(raw == NULL){ fprintf(stderr, "malloc error\n"); exit(1); } for(i=0;i<file_size;i++) raw[i] = (short)((fgetc(fp) << 8) | fgetc(fp)); -----------------------------------------------------

  • VisualC++でのバイナリファイル

    VisualC++でのバイナリファイルのサイズの取得。 Win7 x64 VC++2012 調べた所によると、 バイナリモードではNULL文字を使用できるため、 FILE* fp; fopen_s(&fp,"data.bin","rb"); fseek(fp,0,SEEK_END); size_t fsize=ftell(fp_cl); //fseek(fp,0L,SEEK_SET);//元の位置に戻す。 fclose( fp ); のような感じでサイズを取得してはいけない。 (fseekのSEEK_END動作が不定のため) ……と思っていたのですが、他に方法と言えば、 ファイルを一度全て空読みするくらいしかないので、 試にやってみたところ、上手く行ってしまいます。 一応NULLの入ったバイナリでも正しく取得できてしまいました。 これはCの仕様が変わったためなのか、VC++がたまたま対応しているのか、 どちらでしょうか? また、他に上手い方法があればよろしくお願いいたします。

  • ファイルの大きさを調べたいのですが、、、(C言語)

    2週間前にC言語の勉強を始めたばかりです。 「あるファイルのサイズを見て、メモリを確保し、  読み出した内容をソートして、同じファイルに再び書き出す」 というプログラムを作ろうとしているのですが、 「ファイルのサイズを調べる」という時点でつまづいてしまっています。。。 適当に英数字を書き連ねたファイル(aaa.txt)を、 (fp = fopen(filename,"a+") という形で開いています。 追加読み書きするので"a+"かな? と思ったのですが、、、   //ファイルの終端に移動し、その位置を取得する   fseek(fp1, 0L, SEEK_END);   position = ftell(fp1);   printf("ファイルポインタの位置は %ld です",position); ファイルの大きさを調べるのに、この方法を試してみたのですが、 位置の値が0になってしまいます。。。 filelength(fileno(fp)); でも試してみましたが、 やっぱりファイルサイズが0と返ってきます。 何が原因なのか、何が悪いのかも判らなくて途方に暮れています。 「ここはこう書くんだよ」と、的確なご回答を戴けると幸いです。 基本的な質問で申し訳ありませんが,宜しくお願い致します。

  • C言語のローカル変数の使い方について質問です。

    C言語の変数に関しての質問です。 グローバル変数を使わずに、関数内で宣言したローカルの変数を別のソースファイルで使用することって可能ですか? 例えば、a.cというソースファイルと、b.cというソースファイルがあります。 a.cの関数内で"FILE *fp;"と宣言したローカル変数を、b.cの関数内で共有して使うことはできるのでしょうか。 また、"fp"に直接アクセスはできなくても、間接的にアクセスできる方法があれば教えてください。 下に記述しているのは例え用に適当に書いたプログラムです。 --------------------- a.cのソースファイル --------------------- void Temp(void) { char file_name[128] = {}; errno_t error; FILE *fp; // ←この変数を別のソースで使いたいです scnaf_s("%s", file_name, 128); if(error = fopen_s(&fp, fname, "rb") != 0) { printf("ファイルがオープンできません"); return 0; } fclose(fp); } --------------------- b.cのソースファイル --------------------- void Temp2(void) { int size; // ここでa.cのTemp関数で宣言されている"fp"を使いたい fseek( fp, 0, SEEK_END ); fsize = ftell( fp ); fseek( fp, 0, SEEK_SET ); }

  • fwriteで書き込み

    やりたいことは・・・下に書いていきます。 何がおかしいのか教えてください。 $fp = fopen("example.txt", "r+"); fopenでexample.txtを読み書き可能で開きます。 返り値はポインタですよね。 $fseek = fseek($fp, -3, SEEK_END); $fpで開いたexample.txtのポインタを、ファイルの最後尾から3バイト戻したつもりです。 返り値は 0 成功 -1 失敗 $ftell = ftell($fp); で、今のポインタの位置を確認します。 返り値はポインタ。 fwrite($ftell,$write); $writeの内容を、example.txtの最後から3バイト戻ったところへ書き込み・・・のつもりなのですが。 専門分野ではありませんので、調べてもなかなか進まないです。 ご教授お願いします。

    • ベストアンサー
    • PHP
  • PHPのfopen関数について質問です。

    PHPマニュアル http://www.php.net/manual/ja/function.fopen.php 上記ページの >> Windows ベースのシステムでは \r\n を使用します。 マッキントッシュベースのシステムでは \r を使用します。 間違った改行コードでファイルに書き込むと、 他のアプリケーション上でそのファイルを開いた際に変な風に見えてしまいます。 Windows上では、\nを\r\nに透過的に変換する text-mode変換フラグ('t')が提供されます。 それに対し、'b'を使って強制的にバイナリモードにすることもできます。 その場合データの変換はされません。 このフラグを使用するには、'b' または 't'を mode引数の最後に追加してください。 とある様にPHPにおいてfopen関数の第二引数のモードに付加する場合のバイナリモードとは windows系プラットフォームにおいて書き込む文字列内に[¥n]というバイトがあった場合、プラットフォームにあわせて 自動的に書き出す際に¥r¥nに変換されるから・・・・。 という意味ですよね。 例えば、あるバイナリファイルに奇跡的に[¥n]というバイトがなかった場合、fopen("test.jpg","rw");でもよいということですよね?

    • ベストアンサー
    • PHP
  • ファイル末尾10バイトを削る

    ファイルを開き、末尾10バイトを削り、上書きする というプログラムを作成しています。 とりあえず、以下のようなソースが出来ました。 ------------------------------------------------------------------ ifp = fopen( "openfile.dat", "rb"); ofp = fopen( "outfile.dat", "wb" ); fseek( ifp, -10, SEEK_END ); pos_end = ftell( ifp ); fseek( ifp, 0, SEEK_SET ); for( pos_now = ftell( ifp ) ; pos_now < pos_end; pos_now = ftell( ifp )){    rCnt = fread( pbuf, sizeof( char ), 1, ifp );    f( rCnt == EOF ) break;    fwrite( pbuf, sizeof( char ), 1, ofp ); } fclose( ifp ); *(openfile削除) *(リネーム処理:outfile.dat -> openfile.dat) 以下略 ------------------------------------------------------------------ ソースにあるとおり、 ファイルを開く -> ファイルの末尾10バイト目を記憶する。 -> アウトファイルを開く -> 記憶した位置までコピーする -> オープンファイルの削除 -> リネーム処理 という順番で処理を行っています。 本来は、 ファイルを開く -> ファイルの末尾10バイト目にEOFをいれる -> ファイルを閉じる みたいな感じでやるつもりだったのですが、うまくいきませんでした。 後者のやり方や「私ならこうする!」等アドバイスがありましたら、是非お聞かせください。 よろしくお願いします。

  • fopenでファイルがオープンできません

    $fp = fopen(TEST_FILE, "w") としてオープンしようとすると Warning: fopen(mybasic9.txt): failed to open stream: No such file or directory と、オープンしようとしたファイルがない、と出ます そして、そのファイルをあらかじめ作っておくと OKです。 しかし fopen(TEST_FILE, "w") は該当ファイルがあればそれをオープンし 無ければ、新しく作成する、とFopenの仕様に出ています。 これは、今使っているサーバーの問題でしょうか 何か、避ける方法はないでしょうか よろしくお願いします

    • 締切済み
    • PHP
  • Officeファイルの送受信

    CSocketを使って、Serverとのネットワークプログラムを 作成していますが、ファイルの送受信が上手く出来ず、困っています。 Server側で指定ファイルデータを読み込み、 Client側でファイルを作成し、オープンすると 中身が壊れていますとメッセージが出てしまいます。 下記は、ファイル送受信のためだけに、 暫定的に組んだソースの抜粋になります。 /* Server側のCAsyncSocket派生クラスのSend関数 -------------- */ int CServerSocket::Send( int nFlags ) { FILE *fp; char *pBuffer; fp = fopen( "C:\\a.doc", "rb" ); /* ファイルサイズを取得する */ long current = ftell( fp ); fseek( fp, 0, SEEK_END ); long size = ftell( fp ); fseek( fp, current, SEEK_SET ); /* ファイルデータ読み込み */ pBuffer = new char[size]; fread( pBuffer, sizeof(char), size, fp ); fclose( fp ); return CAsyncSocket::Send( pBuffer, size, nFlags ); } /* Client側のCSocket派生クラスのOnReceive関数 -------------- */ void CClientSocket::OnReceive( int nErrorCode ) { char aaa[22529]; while ( true ){ n_read = Receive( aaa, 22528 ); received += n_read; if ( received >= 22528 ) break; } Close(); ShutDown(); FILE *fp; fp = fopen( "C:\\test.doc", "wb" ); fwrite( aaa, sizeof(char), 22528, fp ); fclose( fp ); } ※テスト版ということで、Client側では、とりあえず、送信サイズ(ファイルデータサイズ)は  分かっているので、固定にしています。 このような送受信では、Officeファイルの送受信はうまく行かないものなのでしょうか?(ちなみにtxtファイルは上手く行きました)

  • C言語のfwrite関数について

    現在,バイナリのデータを処理するプログラムを作成しています。 おおまかに言えば,ファイルA(バイナリモードでオープン)からバイナリでデータを読み込んできて,そのデータを処理してファイルB(バイナリモードでオープン)に書出す,のようなプログラムです。 その処理したデータを入れるデータ型にunsigned long long int型(64bit)を使用しています。 その処理データをファイルBに書出す時に,fwrite関数を用いています(例参照)。 (例) for(i=0; i<N; i++){ fwrite(&c[i], sizeof(c[i]), 1, fp); } //配列cが「unsigned long long int型」です。 //配列cは最初に"0"で初期化しています。 //fpはファイルポインタです。 しかし,本システムでunsigned long long int型が実際に使用しているのは下位32bitです。 上の例で書出した場合,上位32bitの"0"も書出されていることになるのでしょうか。 書出されたファイルのサイズを見れば,64bit全て書出されているようですが,計算間違いで32bitを超えたところまで何かデータが入っている可能性もあります。 どなたはfwrite関数に詳しい方,ご回答をよろしくお願いします。

専門家に質問してみよう