24.1.1 ファイルのオープンとクローズ

ファイルを入出力に使うためには、まず実際のデータの入出力に先立って、 どのファイルをどのように使うかを指定しなければならない。これを ファイルをオープンすると言う。このために使われる関数が、fopen() である。 fopen()の宣言は次のようなものになっている。

    FILE * fopen( char * file_name , char * mode );

ここで直に分かるように、前の節で学んだtypedef を利用した新しい型 の定義が使われていることが推測出来る。実際、FILE型は、 typedefを用いてstdio.h ファイルの中で定義されている構造体 である。fopenを用いてオープンしたファイルに対して入出力をする ためには、このfopen関数の返り値として返される FILE型への ポインタを関数に引数として指定しなければならない。つまり、どのファイル に対して、どの位置に読み書きを行うかという事がこのポインタの指すオブジェクト によって保持されている訳である(つまり、これらの情報をプログラマ−は自分の プログラム中に明示的に保持するようにしなくても良い訳である)。

fopen()関数に与える引数は、文字列で与えられる。最初の引数は ファイル名を与えるが、この際に注意するべきなのはファイル名はパスを 含めて考えなければならない。つまり、 絶対パスで与えるか、相対パスで与えるかによって動作が違うようになっている 。また、この際のパスを含めたファイルの指定方法はシステムによって異なる (つまりはシステムの固有の方法にのっとって行わなければならず、C言語では 一般の命名規則を与えていない。例えば、UnixとMS-DOS系ではパスの区切りから して異なっている)。

2番目の引数には、ファイルを読み込み用に用いるのか、それとも書き込みなの かと言った用途に基づいた指定を文字列を用いて指定するようになっている。

例えば、"test.data" というファイルを読み込みようにオープンするには 以下のように指定する。
#include <stdio.h>
...
    FILE * fp;
    ...
    fp = fopen("test.data", "r");
うまくオープン出来れば、ファイルポインタ fpにはファイル構造体 オブジェクトへのアドレスが入るが、もしファイルが存在しないなどの理由で オープンに失敗した場合には NULLポインタが返るようになっている。 従って、ファイルをオープンする際には必ずエラーチェックをするようにした 方が良いであろう。
    FILE * fp;
    char * file_name="test.data";
    ...
    if( (fp = fopen(file_name, "r")) == NULL){
        printf("Error: cannot open file(%s)\n", file_name);
        exit(1);
    }

同じように、書き込み用にファイルをオープンするには、 以下の様に行う。
    FILE * fp;
    char * file_name="test.data";
    ...
    fp = fopen(file_name, "w");
もし、このファイルが存在しない場合にはファイルが新たに自動的に作成 されるが、逆に存在した場合にはそのファイルの中身は全て消され、ファイル の大きさが0になってしまうので注意しなければならない。ちなみに、もしも 書き込み権限などの問題でファイルが作成出来ない場合には NULL ポインタが返るので、やはりエラーチェックは必要である。

このように write モードではファイルを消してしまう事になるので、ファイル を消さずに書き込みを行うには append モードを用いる。
    fp = fopen(file_name, "a");
この場合、もしファイルが存在したならば、そのファイルの最後に追加して 書き込みがなされる。ファイルが存在しないならば、新たに作成される点は writeモードと同じである。

更に、これらの read, write, append モードに加えて、読み書き両方を可能 にするための、言わば更新用の指定がある。更新はこれまでの "r","w","a" の文字列に "+" を加える事で指定がされる。注意しなければならないのは、 read, write, append の各モードに対して指定するので、ファイルの消去など の問題はモード毎に考えなければならない。以下は、ファイルの更新用に read/write モードで開く場合である。
    fp = fopen(file_name, "r+");
この場合、read モードの更新用にオープンしているので、ファイルは存在 しなければならない。また、書き込みが出来るのであるが、どこに書き込まれる かという問題があるであろう。実は、ファイル構造体オブジェクトには ファイル中のどの位置を現在見ているのかという情報が保持されている。 これはカレントポジション(現在位置)などとも呼ばれるが、読み書きは常に このカレントポジションに対して行われるようになっている。従って、問題は 最初にファイルをオープンした際に、カレントポジションは何処に置かれている のかという事になるのだが、read,writeモードはファイルの先頭、append モードはファイルの終わりにあるという事になっている。従って、更新用の 指定をした場合でも、この性質は引き継がれることになっているので、同じ 更新用でも read, write, append のどのモードかによってカレントポジションは 違う事になる。同様に、ファイルが新設されるのか、あるいはファイルの 中身が消されてしまうのかという点も同じである。

モードについてまとめると以下のようになる。

指定文字 モード カレントポジション ファイルの作成
r read 先頭 作成されない。無ければエラー
w write 先頭 無ければ作成。あれば0に。
a append 末尾 無ければ作成
r+ read,write 先頭 作成されない。無ければエラー
w+ read,write 先頭 無ければ作成。あれば0に
a+ read,write 末尾 無ければ作成。

実際の入出力については次の項目で取り扱うことにして、入出力が終了し、 ファイルの読み書きを終了し、オープンしたファイルをクローズする際には fclose() を用いる。

    int  fclose( FILE *fp );

fclose() は引数にクローズするファイルのファイルポインタを与え、 返り値には、成功した場合は 0 が、失敗した場合には EOF が返る。 但し、プログラムの終了時には必ずオープンしたファイルは全てクローズされ るので明示的に指定しなくても良いが、モードを変更したい場合(readモード で読み込み、appendモードで書き込みたい場合など)は明示的にクローズし なければならない(他にも、あまりにも多数のファイルをオープンしすぎて、 システムで許されている量を越えた場合にも不要なファイルをクローズしな ければならない事もある)。
    FILE * fp;
    char * file_name="test.data";
    ...
    if( (fp = fopen(file_name, "r")) == NULL){
        printf("Error: cannot open file(%s)\n", file_name);
        exit(1);
    }
    ...
    fclose(fp);



最初のページ 戻る 次へ 最後のページ 目次
Hiroyasu Asami