ファイル入出力

データの読み込みや書き出しをファイルに対して行なうための 関数が fopen/fclose である。

ファイルの読み込み

ファイルから、データを読むためには以下の手順を取る。

  1. ファイル構造体のポインタ変数を宣言
  2. fopen関数でファイルを開く
  3. fgetsで読み込む
  4. fclose関数でファイルを閉じる

さっそく具体例を見よう。まず、ファイルを使わず、標準入力から 読んだデータを行番号をつけて表示するプログラム。

cat-n.c

#include <stdio.h>
#define BUF_LEN	200

int main()
{
  char buffer[BUF_LEN];
  int  n=0;
  while (NULL != fgets(buffer, sizeof buffer, stdin)) {
    printf("%4d: %s", ++n, buffer);
  }
}

実行してデータを与えるときはキーボード、またはパイプラインを 利用する。

% ./cat-n    (キーボードからデータを入れる場合)

% cat aisatsu.c | ./cat-n  (aisatsu.cをデータとして与える場合)

では、データを必ず aisatsu.c (第4回に作った) から読み込むように fopen, fclose を利用して改良してみよう。

fcat.c

#include <stdio.h>
#define BUF_LEN	200

int main()
{
  FILE *aisatsuin;
  char buffer[BUF_LEN];
  int  n=0;
  aisatsuin = fopen("aisatsu.c", "r");
  while (NULL != fgets(buffer, sizeof buffer, aisatsuin)) {
    printf("%4d: %s", ++n, buffer);
  }
  fclose(aisatsuin);
}

コンパイルし、プログラムを起動すると自動的にデータファイルとして aisatsu.c を開き、行番号をつけた結果を出力する。

ファイルから入力させるために施した修正点について説明しよう。

ファイルへの書き出し

リダイレクト

printfputs関数は、文字列を 標準出力 (stdout; STandar OUTput) に書き出す。 標準出力はとくに指定しなければ「画面」になる。これを別のファイルに 振り替えるにはコマンドラインで > 記号を使う。

% cat aisatsu.c | ./cat-n > hogehoge.out

とすると、元々画面に出ていた結果と全く同じものが hogehoge.out ファイルに出力される。このように出力を 別のファイルに切り替えることを出力のリダイレクトという。 リダイレクトによる出力先の切り替えはシェルの持っている機能であり、 C言語プログラムではない。

シェルとは普段コマンドを打つときに使っているプログラムである。

fopenによるファイルへの書き出し

fopen関数で書き込みのできるモードでオープンしたファイル にはfprintf関数で書き出せる。

FILE *kakikaki;
  :
kakikaki = fopen("hello.dat", "w");
  :
fprintf(kakikaki, "Hello, world!\n");
  :
fclose(kakikaki);

fprintf関数は、printf関数と同様に 書式つきの出力を行なう。第1引数に出力先ストリームを指定する点を 除いてprintf関数と同じだと思って良い。

printf("%s は %d 円です.\n", item, price);
  は以下と同じ
fprintf(stdout, "%s は %d 円です.\n", item, price);

例外処理

fopen を利用したプログラムでは、

開こうとしたファイルが存在しない!!

ということがごく普通にありうるので、プログラムを書くときは、 「開くファイルがなかった場合」つまり、fopen()に 失敗した場合を必ず考えなければならない。具体的には、fopen() 関数の返却値が NULL の場合の対処を書く必要がある。

開こうとしたファイルがなかったら、続く処理が何もできないことが 多いだろうから、以下のような流れを書けば良い。

FILE *datafile;
char buf[100];
datafile = fopen("hissu.data", "r");
if (NULL == datafile) {
  fprintf(stderr, "hissu.data ファイルを用意して下さい\n");
  exit(1);    /* exitはプログラムの実行を終了 */
}
while (NULL != fgets(buf, 100, datafile)) {
  :
  : (本当の処理)
}

fprintfの出力先として指定している stderrは、標準エラー出力 と呼ばれるもので、 エラーメッセージを出すためのストリームである。エラーメッセージを

if (NULL == datafile) {
  /* ↓ エラーメッセージにprintfはダメ! */
  printf("hissu.data ファイルを用意して下さい\n");
  exit(1);    /* exitはプログラムの実行を終了 */
}

のように標準出力に出した場合

% cat aisatsu.c | ./cat-n > hogehoge.out

のように、リダイレクトされた場合エラーメッセージまで hogehoge.out ファイルに行ってしまって、エラーになったかどう かが利用者には分からない。標準エラー出力 (stderr)に出すようにすれば、たとえリダイレクトされても 必ず画面にメッセージが出るようになる。


目次