プログラムの外にあるデータを読み込んだり逆に外にデータを書き出す方法は色々ありますが、一番基本的な方法はストレージに置いてあるファイルを読み書きすることだと思います。実際に読み書きする前に、まずここではファイルをオープンしてクローズする方法について学びます。
さて皆さんがノートの内容を読みたい時とか文字を書きたい時とかにノートを開く様に、プログラムがファイルを読み書き可能にする処理の事を「ファイルをオープンする」とか「ファイルを開く」とか言います。
ファイルをオープンするために C 言語では「fopen 標準関数」を使います。fopen 標準関数の使い方と使用例は以下の通りです。
※ この関数は古い関数でセキュリティ的に危険なので使わない方が良いです。 何故危険なのかは自分で調べてみましょう。 C11以降は「fopen_s」を代わりに使うことが推奨されています。
fopen( ファイル名, モード )
戻り値: オープンに成功したらファイルポインタ(※)、エラーなら NULL が返る。
※ 正確には FILE 構造体型変数のポインタ
モード: どの様にファイルをオープンするか指定する。
モード | 説明 | ファイルがある時 | ファイルが無い時 |
---|---|---|---|
"w" | ファイルにデータを新規で書き込む (writing) | 古い内容を消してから上書き | 書き込み可なら新規作成、不可ならエラー |
"r" | ファイルからデータを読み込む (reading) | 先頭から読み出し | エラーを返す |
"a" | ファイルにデータを追加する (appending) | 古い内容の後に追加書き込み | 書き込み可なら新規作成、不可ならエラー |
※ 各モードの後に + を追加した "w+" / "r+" / "a+" も指定できますが、今回は fseek 標準関数を扱わないので説明は省きます。詳しくは自分で調べて下さい。
(使用例1: ファイル名を直接指定) FILE *fp1 = NULL; // fp1 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う FILE *fp2 = NULL; // fp2 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う fp1 = fopen( "hoge.txt", "w" ); // hoge.txt を書き込み(writing)モードでオープン。fp1 使用 fp2 = fopen( "fuga.txt", "r" ); // fuga.txt を読み込み(reading)モードでオープン。fp2 使用
(使用例2: ファイル名を文字列配列で指定) FILE *fp1 = NULL; // fp1 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う FILE *fp2 = NULL; // fp2 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う char f1[256] = "hoge.txt"; // const char *f1 = "hoge.txt"; と書くのが一般的 char f2[256] = "fuga.txt"; // const char *f2 = "fuga.txt"; と書くのが一般的 fp1 = fopen( f1, "w" ); // hoge.txt を書き込み(writing)モードでオープン。fp1 使用 fp2 = fopen( f2, "r" ); // fuga.txt を読み込み(reading)モードでオープン。fp2 使用
上のモードの表で示した様に、書き込み出来ないデバイスにファイルを書き込もうとしたり、存在しないファイルを読もうとしたりすると fopen 標準関数はエラーとなり、ファイルポインタに NULL が入ります。
この時そのままプログラムを続けると、ファイルを読み書きしようとした瞬間にいきなりプログラムがクラッシュしますので、「ファイルのオープンに失敗しました」の様なエラーメッセージを出してプログラムを強制終了してあげるとユーザーフレンドリーになって好ましいです。
さてエラーメッセージを出してプログラムを強制終了させたい時に便利な標準関数として exit 標準関数が用意されています。使い方は以下の通りです。
※ stdlib.h をインクルードする必要があります。
※ C11以降ならより高速化された「quick_exit」も使えます。
exit(終了コード)
戻り値: 無し
終了コード: OS にプログラムがどう終了したかを知らせるための数字
終了コード | 説明 | 備考 |
---|---|---|
EXIT_FAILURE | 異常終了 | 数字の 1でも代替可 |
EXIT_SUCCESS | 正常終了 | 数字の 0でも代替可 |
(使用例: 強制的に異常終了) exit(EXIT_FAILURE); 又は exit(1);
(使用例: 強制的に正常終了) exit(EXIT_SUCCESS); 又は exit(0);
では exit 標準関数を使って fopen 時のエラー処理をする例を示します。
※ stdlib.h のインクルードを忘れずに FILE *fp1 = NULL; // fp1 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う FILE *fp2 = NULL; // fp2 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う char f1[256] = "hoge.txt"; // const char *f1 = "hoge.txt"; と書くのが一般的 char f2[256] = "fuga.txt"; // const char *f2 = "fuga.txt"; と書くのが一般的 fp1 = fopen( f1, "w" ); // hoge.txt を書き込み(writing)モードでオープン。fp1 使用 if( fp1 == NULL ){ // hoge.txt を書き込みオープン出来なかったら fp1 に NULL が入る printf("%s のオープン失敗\n", f1); exit(EXIT_FAILURE); // 強制的に異常終了。exit(1)でも可 } fp2 = fopen( f2, "r" ); // fuga.txt を読み込み(reading)モードでオープン。fp2 使用 if( fp2 == NULL ){ // fuga.txt を読み込みオープン出来なかったら fp2 に NULL が入る printf("%s のオープン失敗\n", f2); exit(EXIT_FAILURE); // 強制的に異常終了。exit(1)でも可 } // ここまで処理が進んだら hoge.txt と fuga.txt のオープンに成功しているので // fp1, fp2 を使ってファイルの読み書きが出来る
プログラムがあるファイルを読み書きしている間はそのファイルにロックがかかって他のプログラムはアクセス出来ません。そこでファイルを使い終わったら終了処理をする必要があります。ファイルを使い終わった時の終了処理の事を「ファイルをクローズする」とか「ファイルを閉じる」とか言います。
ファイルをクローズするために C 言語では「fclose 標準関数」を使います。fclose 標準関数の使い方と使用例は以下の通りです。
fclose(ファイルポインタ)
戻り値: 終了コード(普通は使わない)
(使用例) fclose(fp);
では fopen → エラー処理 → fclose までの流れの例を示したいと思います。
なお、下のコードを実行してもまだ読み書きの部分を作っていませんので何もおきません(空っぽの hoge.txt は出来ますが)。読み書きの方法についてはデータの種類別に次のページ以降で学んで行きます。
※ stdlib.h のインクルードを忘れずに FILE *fp1 = NULL; // fp1 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う FILE *fp2 = NULL; // fp2 を「ファイルポインタ」と呼び、ファイルの読み書き時に使う char f1[256] = "hoge.txt"; // const char *f1 = "hoge.txt"; と書くのが一般的 char f2[256] = "fuga.txt"; // const char *f2 = "fuga.txt"; と書くのが一般的 fp1 = fopen( f1, "w" ); // hoge.txt を書き込み(writing)モードでオープン。fp1 使用 if( fp1 == NULL ){ // hoge.txt を書き込みオープン出来なかったら fp1 に NULL が入る printf("%s のオープン失敗\n", f1); exit(EXIT_FAILURE); // 強制的に異常終了。exit(1)でも可 } fp2 = fopen( f2, "r" ); // fuga.txt を読み込み(reading)モードでオープン。fp2 使用 if( fp2 == NULL ){ // fuga.txt を読み込みオープン出来なかったら fp2 に NULL が入る printf("%s のオープン失敗\n", f2); exit(EXIT_FAILURE); // 強制的に異常終了。exit(1)でも可 } // ここまで処理が進んだら hoge.txt と fuga.txt のオープンに成功しているので // fp1, fp2 を使ってファイルの読み書きが出来る fclose(fp1); // hoge.txt のクローズ fclose(fp2); // fuga.txt のクローズ