next up previous contents
Next: 25.1.2 一文字の読み書き Up: 25.1 ストリーム入出力 Previous: 25.1 ストリーム入出力

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

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

#include <fstream.h>
...
    ifstream fin;
    fin.open( "newfile.txt" );

cin を用いて出力するやり方に少し似ているが、自分で fin という変数 を宣言しなければならない点が少し違う。また、宣言した後に、どのファイル に対して読み書きを行うかを指定するために、ファイル名を open()を用いて 指定しなければならない。 この際に注意するべきなのはファイル名はパスを 含めて考えなければならない。つまり、 絶対パスで与えるか、相対パスで与えるかによって動作が違うようになっている 。また、この際のパスを含めたファイルの指定方法はシステムによって異なる (つまりはシステムの固有の方法にのっとって行わなければならず、C言語では 一般の命名規則を与えていない。例えば、UnixとMS-DOS系ではパスの区切りから して異なっている)。

更に、open() には、上の例では1つしか引数がないが、複数を指定 する事が出来るようになっている。 2番目の引数には、ファイルを読み込み用に用いるのか、それとも書き込みなの かと言った用途に基づいた指定を文字列を用いて指定するようになっている。

例えば、"test.data" というファイルを読み込みようにオープンするには 以下のように指定する。
#include <fstream.h>
...
    ifstream fin;
    ...
    fin.open("test.data", ios::in);
(実は、2番目の引数を省略した場合のデフォルトが ios::in に なっている。)

うまくオープン出来れば、cin の場合と同じように fin を用いて、 エラーチェックが出来るようになっている。
#include <fstream.h>
...
    ifstream fin;
    ...
    fin.open("test.data", ios::in);
    if( !fin ){
        cout << "Error: cannot open file(" << file_name << ")" << endl;
        exit(1);
    }

同じように、書き込み用にファイルをオープンするには、 以下の様に行う。

#include <fstream.h>
...
    ofstream fout;
    ...
    fout.open("test.data", ios::out);
    ...
もし、このファイルが存在しない場合にはファイルが新たに自動的に作成 されるが、逆に存在した場合にはそのファイルの中身は全て消され、ファイル の大きさが0になってしまうので注意しなければならない。ちなみに、もしも 書き込み権限などの問題でファイルが作成出来ない場合にはfoutを用いて、 やはりエラーチェックが出来る。 ( fout.open() の場合も2番目の引数を省略するとデフォルト値は ios::out になっている。)

このように ios::out モードではファイルを消してしまう事になるので、ファイル を消さずに書き込みを行うには ios::app モードを用いる。
    char *file_name="test.data";
    ...
    fout.open(file_name, ios::app);
この場合、もしファイルが存在したならば、そのファイルの最後に追加して 書き込みがなされる。ファイルが存在しないならば、新たに作成される点は ios::outモードと同じである。

更に、ifstream, ofstream に対して、 読み書き両方を可能 にするための、言わば更新用の指定がある。 以下は、ファイルの更新用に read/write モードで開く場合である。

    fstream fio;
    ...
    fio.open(file_name, ios::in | ios::out );
この場合、注意しなければならないのは、ファイルが存在しない場合には 新しく作成され、存在する場合にはファイルのどこから書き込むのかという 問題が生じる。なぜならば、ファイルをオープンした場合には ファイル中のどの位置を現在見ているのかという情報が保持されているから である。 これはカレントポジション(現在位置)などとも呼ばれるが、読み書きは常に このカレントポジションに対して行われるようになっている。従って、問題は 最初にファイルをオープンした際に、カレントポジションは何処に置かれている のかという事になるのだが、ios::in,ios::out モードはファイルの先頭、ios:app はファイルの末尾ということになっている。

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

    fstream fio;
    ...
    fio.open(file_name, ios::in | ios::out );
    ...
    fio.close();

但し、プログラムの終了時には必ずオープンしたファイルは全てクローズされ るので明示的に指定しなくても良いが、モードを変更したい場合(readモード で読み込み、appendモードで書き込みたい場合など)は明示的にクローズし なければならない(他にも、あまりにも多数のファイルをオープンしすぎて、 システムで許されている量を越えた場合にも不要なファイルをクローズしな ければならない事もある)。
    ifstream fin;
    char * file_name="test.data";
    ...
    if( !fin.open(file_name, ios::in)){
        cout << "Error: cannot open file(" << file_name << ")" << endl;
        exit(1);
    }
    ...
    fin.close(fp);



Noriyo Kanayama