第22章 fopen / fread / fwrite / fclose 関数

 ファイル記述子でなくFILEストリームを使いたい場合は fopen / fread / fwrite / fclose 関数を使うことができます。

 とりえあえず関数の宣言から見てきましょう。

#include <stdio.h>

FILE *fopen(const char *pathname, const char *mode);

int fclose(FILE *stream);

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

 fopen の mode は以下の 6 種類あります。

r
読み込みの為に開きます。
r+
書き込みと読み込みの両用で開きます。
w
書き込みのために開きます。
w+
書き込みと読み込みの両用で開きます。
a
アペンドの為に開きます。
a+
アペンドと読み込みの為に開きます。

 FILEストリームは fprintf で使った stdout や stderr に相当するものです。

 ストリームは FILE オブジェクトを指しているポインターなので、ファイル記述子とは別物です。

 まあさして重要じゃないんで、実装例を軽く見るだけで良いでしょう。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <fcntl.h>
  4 #define BUFFER_SIZE 8192
  5
  6 int main(int argc, char **argv)
  7 {
  8   int size;
  9   FILE *stream;
 10   char buf[BUFFER_SIZE];
 11
 12   if (argc != 2) {
 13     fprintf(stderr, "ファイル名を指定してください\n");
 14     exit(1);
 15   }
 16
 17   stream = fopen(argv[1], "r");
 18
 19   if (stream == NULL) {
 20     fprintf(stderr, "%s を開けませんでした\n", argv[1]);
 21     exit(1);
 22   }
 23
 24   size = 1;
 25   while (size > 0) {
 26     size = fread(buf, 1, BUFFER_SIZE, stream);
 27     if (size > 0) {
 28       fwrite(buf, 1, size, stdout);
 29     }
 30   }
 31   fclose(stream);
 32   return 0;
 33 }

ビルドと実行結果. 

$ echo "abcde" > "abc.txt"
$ echo "12345" >> "abc.txt"
$ gcc main.c
$ ./a.out abc.txt
abcde
12345

 まずは変数から説明しますかね。

  8   int size;
  9   FILE *stream;
 10   char buf[BUFFER_SIZE];

 size は fread() 関数の返り値を保持する変数として使います。

 読みこんだバイトサイズですね。

 stream は FILE オブジェクトを指すポインターです。

 ここでは fopen() の返り値となりますが、読み込み専用の指定をしているので入力ストリームとでも読んでおきましょう。

 17   stream = fopen(argv[1], "r");

 ファイルシステムから読み込んだデータをメモリーへ保持するために使う変数が buf です。

 24   size = 1;
 25   while (size > 0) {
 26     size = fread(buf, 1, BUFFER_SIZE, stream);
 27     if (size > 0) {
 28       fwrite(buf, 1, size, stdout);
 29     }
 30   }

 正直 BUFFER_SIZE が大きめなので while 文を使うまでもないんですけど、本当に大きいデータを読みこむならループにしておきます。

 まず fread() が stream から BUFFER_SIZE バイトを読み込うとします。

 それで size が 0 以上ならば fwrite() で標準出力をします。

 この際に出力に使うサイズは fread の返り値を保持する size 変数を使っています。

Copyright 2018-2019, by Masaki Komatsu