Linux講座にようこそ。このページは「C言語プログラミング入門 - 第14章.ライブラリ関数 - 入出力ライブラリ」です。

C言語プログラミング入門

14. ライブラリ関数(9/36) - 入出力ライブラリ(8/10)

14.12 バッファ操作関数

通常、ファイルはハードディスク(HDD)に作成しますが、ハードディスクの動作はCPUやメモリと比べると大変に低速です。これをカバーするために、出力データをメモリ上のバッファ領域に溜め込んでおき、バッファが満杯になったあるいは、一定時間経過した時点でハードディスクに出力する、といったことを行っています。通常は、これで問題ないと思いますが、入出力データや媒体の種類により、バッファを経由したくないことがあるかもしれません。そのような場合は、ここで紹介する関数を使うとよいでしょう。なお、強制的にバッファの内容を出力するにはfflush関数を使用します。

バッファリングには、次の3つの方法があります。

  • unbufferedはバッファリングを行わずに、すぐに出力します。
  • fully bufferedは通常のバッファリングで、入出力データはバッファ経由で入出力します。
  • line bufferedは新しい行が出力されるか、新しい行が入力されるまでバッファに溜め込みます。

14.12.1 setvbuf関数

setvbuf関数はバッファリング方法(バッファリング・モード)とバッファ領域を設定します。この関数はファイルオープン後で、入出力関数を呼び出す前に使用します。

【表14-1-35】 setvbuf関数
形式#include <stdio.h>
int setvbuf(FILE *fp, char *buf, int mode, size_t size);
返り値正常に処理ができた場合は0を返します。エラーの場合は0以外を返します。
引数
FILE *fp
入力または、出力するファイルのファイルポインタを指定します。
char *buf
バッファ領域を指定します。バッファ領域は第4引数のsize以上の容量が必要です。なお、NULLを指定するとシステムで用意したバッファを使用します。
int mode
バッファリング方法(バッファリング・モード)を、次の値で指定します。
_IONBF
unbufferedです。
_IOFBF
fully bufferedです。
_IOLBF
line bufferedです。
size_t size
バッファの大きさを指定します。第2引数にNULLを指定した場合は0を指定します。

14.12.2 setbuf関数

setbuf関数はバッファ領域を設定します。

【表14-1-36】 setbuf関数
形式#include <stdio.h>
void setbuf(FILE *fp, char *buf);
返り値ありません。
引数
FILE *fp
入力または、出力するファイルのファイルポインタを指定します。
char *buf
バッファ領域を指定します。

14.12.3 例題

実行時引数として2つのファイルパス名を指定して、ファイルのコピーを行います。入力ファイルに対してはバッファ領域を指定し、出力ファイルに対してはバッファリングを行わない指定をしています。なお、ソースファイルの行数を少なくしてプログラムのポイントを明確にするため、エラー処理は省略しています。

  1. #include <stdio.h>
  2. #define IOB_SIZE 4096
  3. #define LINE_SIZE 1024
  4.  
  5. int main(int argc, char **argv)
  6. {
  7.     FILE    *fp_src;                   /* コピー元ファイル */
  8.     FILE    *fp_dest;                  /* コピー先ファイル */
  9.     char    src_iobuff[IOB_SIZE];      /* コピー元IOバッファ */
  10.     char    line[LINE_SIZE];
  11.  
  12.     fp_src = fopen(*(argv + 1), "r");
  13.     setvbuf(fp_src, src_iobuff, _IOFBF, IOB_SIZE);
  14.  
  15.     fp_dest = fopen(*(argv + 2), "w");
  16.     setvbuf(fp_dest, (char *)NULL, _IONBF, 0);
  17.  
  18.     while(fgets(line, LINE_SIZE, fp_src) != NULL)
  19.     {
  20.         fputs(line, fp_dest);
  21.     }
  22.  
  23.     fclose(fp_dest);
  24.     fclose(fp_src);
  25.  
  26.     return 0;
  27. }
$ cat /etc/issue ← catコマンドで/etc/issueファイルの内容を確認します
Fedora release 8 (Werewolf)
Kernel \r on an \m

$ ./ex14_1_11.prg /etc/issue ./temp.txt ← 実行時引数に/etc/issue指定して実行します
$ cat ./temp.txt
Fedora release 8 (Werewolf)
Kernel \r on an \m

$
2行目
バッファ領域の大きさをIOB_SIZEというマクロ名で宣言します。
9行目
バッファ領域として使用する配列を宣言します。容量は4096バイトです。
13行目
入力ファイル用のバッファ領域として、9行目で宣言しているsrc_iobuffを指定します。バッファリング・モードはfully bufferedです。
16行目
出力ファイルはバッファリングをしない指定をします。(バッファリング・モードはunbufferedです)