言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

C言語辞典

  1. トップページ
  2. C言語辞典
  3. fopen() / fclose() / freopen()

fopen() / fclose() / freopen()

対応: C89(1989)

ファイルを開いたり閉じたりするための基本的な関数です。『<stdio.h>』に定義されており、ファイル操作を行うすべての処理の起点になります。ファイルはオープンしたら必ずクローズする必要があります。

構文

// ファイルをオープンして FILE ポインタを返します。
// 戻り値: 成功時は FILE ポインタ、失敗時は NULL。
FILE *fopen(const char *filename, const char *mode);

// ファイルをクローズします。
// 戻り値: 成功時は 0、エラー時は EOF。
int fclose(FILE *stream);

// 既存の FILE ポインタを別のファイルに結び付けます(リダイレクトに便利)。
// 戻り値: 成功時は stream、失敗時は NULL。
FILE *freopen(const char *filename, const char *mode, FILE *stream);

モード文字列一覧

モード概要
"r"読み込み専用でオープンします。ファイルが存在しない場合は NULL を返します。
"w"書き込み専用でオープンします。ファイルが存在しない場合は新規作成、存在する場合は内容を消去します。
"a"追記モードでオープンします。ファイルが存在しない場合は新規作成、存在する場合は末尾から書き込みます。
"r+"読み書き両用でオープンします。ファイルが存在しない場合は NULL を返します。
"w+"読み書き両用でオープンします。存在する場合は内容を消去します。
"a+"読み書き両用の追記モードでオープンします。書き込み位置は常に末尾です。
"rb", "wb" 等バイナリモードでオープンします。テキストモードとの違いは改行文字の扱いです(Windows 環境で重要)。

サンプルコード

sample_fopen_fclose.c
#include <stdio.h>

int main(void) {
    // "w" モードでファイルを作成し、テキストを書き込みます。
    FILE *fp = fopen("sample.txt", "w");
    if (fp == NULL) {
        // fopen が失敗した場合(パスが存在しない・権限がないなど)。
        perror("fopen");
        return 1;
    }
    fprintf(fp, "1行目のテキストです\n");
    fprintf(fp, "2行目のテキストです\n");
    fprintf(fp, "3行目のテキストです\n");
    fclose(fp); // 書き込み後は必ずクローズします。

    // "r" モードで先ほど作成したファイルを読み込みます。
    fp = fopen("sample.txt", "r");
    if (fp == NULL) {
        perror("fopen");
        return 1;
    }
    char buf[256];
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        printf("%s", buf); // 1行ずつ標準出力に表示します。
    }
    fclose(fp);

    // "a" モードで追記します(既存の内容は保持されます)。
    fp = fopen("sample.txt", "a");
    if (fp == NULL) {
        perror("fopen");
        return 1;
    }
    fprintf(fp, "4行目(追記)です\n");
    fclose(fp);
    printf("追記が完了しました。\n");

    return 0;
}

コンパイルして実行すると次のようになります。

gcc sample_fopen_fclose.c -o sample_fopen_fclose
./sample_fopen_fclose
1行目のテキストです
2行目のテキストです
3行目のテキストです
追記が完了しました。

freopen でストリームを切り替える

freopen は既存の FILE ポインタを別のファイルに結び付けます。標準出力をファイルにリダイレクトする場合などに使います。

freopen_example.c
#include <stdio.h>

int main(void) {
    printf("これは標準出力に出力されます。\n");

    if (freopen("stdout_log.txt", "w", stdout) == NULL) {
        perror("freopen");
        return 1;
    }

    printf("これはファイルに書き込まれます。\n");
    printf("標準出力がリダイレクトされています。\n");

    fclose(stdout);

    FILE *fp = fopen("stdout_log.txt", "r");
    if (fp == NULL) { perror("fopen"); return 1; }
    char buf[128];
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        fprintf(stderr, "ファイル内容: %s", buf);
    }
    fclose(fp);
    return 0;
}

コンパイルして実行すると次のようになります。

gcc freopen_example.c -o freopen_example
./freopen_example
これは標準出力に出力されます。
ファイル内容: これはファイルに書き込まれます。
ファイル内容: 標準出力がリダイレクトされています。

バイナリモードでのファイル操作

バイナリデータを扱う場合は "rb" / "wb" でファイルを開きます。テキストモードでは改行変換が行われるため、バイナリデータが壊れることがあります。

fopen_binary.c
#include <stdio.h>

int main(void) {
    unsigned char data[] = {0x00, 0x01, 0xFF, 0x7F, 0x80};
    int n = (int)(sizeof(data) / sizeof(data[0]));

    FILE *fp = fopen("binary.bin", "wb");
    if (fp == NULL) { perror("fopen"); return 1; }
    fwrite(data, sizeof(unsigned char), n, fp);
    fclose(fp);

    unsigned char buf[8] = {0};
    fp = fopen("binary.bin", "rb");
    if (fp == NULL) { perror("fopen"); return 1; }
    size_t read_n = fread(buf, sizeof(unsigned char), n, fp);
    fclose(fp);

    printf("読み込んだバイト数: %zu\n", read_n);
    for (size_t i = 0; i < read_n; i++) {
        printf("0x%02X ", buf[i]);
    }
    printf("\n");
    return 0;
}

コンパイルして実行すると次のようになります。

gcc fopen_binary.c -o fopen_binary
./fopen_binary
読み込んだバイト数: 5
0x00 0x01 0xFF 0x7F 0x80

よくあるミス

よくあるミス: NULL チェックの省略

fopen が返す NULL をチェックしないと、ファイルが存在しない場合にプログラムがクラッシュします。

fopen_null_ng.c
#include <stdio.h>

int main(void) {
    FILE *fp = fopen("nonexistent.txt", "r");
    /* NG: NULL チェックなし */
    char buf[64];
    fgets(buf, sizeof(buf), fp); /* fp が NULL なのでクラッシュする */
    printf("%s", buf);
    fclose(fp);
    return 0;
}

修正後は次の通りです。

gcc fopen_null_ng.c -o fopen_null_ng
./fopen_null_ng
Segmentation fault (core dumped)
fopen_null_ok.c
#include <stdio.h>

int main(void) {
    FILE *fp = fopen("nonexistent.txt", "r");
    if (fp == NULL) {
        perror("fopen");
        return 1;
    }
    char buf[64];
    while (fgets(buf, sizeof(buf), fp) != NULL) {
        printf("%s", buf);
    }
    fclose(fp);
    return 0;
}

修正後は次の通りです。

gcc fopen_null_ok.c -o fopen_null_ok
./fopen_null_ok
fopen: No such file or directory

概要

『fopen()』が返す FILE ポインタは、ファイルの読み書き位置や状態を管理する構造体へのポインタです。このポインタを『fgets()』・『fread()』・『fseek()』など各ファイル操作関数に渡して使用します。

fopen() の戻り値は必ず NULL チェックをしてください。ファイルが存在しない場合や権限がない場合に NULL が返ります。チェックを怠るとヌルポインタ参照でプログラムがクラッシュします。

オープンしたファイルは必ず fclose() でクローズしてください。クローズしないと書き込みバッファがフラッシュされず、データが正しく保存されないことがあります。また、オープンできるファイル数にはシステムの上限があり、クローズしないとリソースリークが発生します。

ファイルを1行ずつ読み込む場合は『fgets()』、バイナリデータの読み書きには『fread() / fwrite()』を使用してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。