本文へスキップ
BecomeCoder

C言語コース · 第11章 ファイル入出力 · レッスン42

fopen/fclose ― ファイルを開く・閉じる

ブラウザで完結

導入

次に起動したときも同じデータを使いたい、実行結果を他のプログラムに渡したい——そんなときに使うのが「ファイル」への保存です。C言語では fopen でファイルを開き、fclose で閉じることでファイルを操作します。

説明

ファイルを開くには次のように書きます。

FILE *fp = fopen("パス", "モード");

モードには代表的に次の3つがあります。

  • "r" … 読み込み専用。ファイルが存在しないと失敗する。
  • "w" … 書き込み専用。ファイルが無ければ新規作成、あれば中身を空にしてから書き込む(上書き)。
  • "a" … 追記専用。ファイルの末尾にどんどん追加していく。無ければ新規作成。

fopen の戻り値は FILE 型へのポインタ(FILE *)です。ファイルを開けなかった場合(存在しない・権限がない等)は特別な値 NULL が返ります。開けたかどうかを確かめずに使うと危険なので、必ず if (fp == NULL) { ... } でチェックしてから使う癖をつけましょう。使い終わったファイルは fclose(fp); で必ず閉じます。閉じ忘れると、書き込んだ内容が確定しない場合があります。

flowchart LR
  w["fopen(path, \"w\")"] --> fp["fputs(...) で書き込む"] --> c1["fclose(fp)"]
  c1 --> r["fopen(path, \"r\")"]
  r --> read["fgetc(fp) を繰り返して読む"] --> c2["fclose(fp)"]

次の例では、/home/user/memo.txt というファイルに1行書き込んでから、同じファイルを読み込みモードで開き直し、1文字ずつ fgetc で読み出して表示しています(1文字ずつ読む関数fgetc。行ごとまとめて読む方法は次のレッスン以降で学びます)。最後に、存在しないファイルを "r" で開こうとして NULL が返る様子も確認します。

#include <stdio.h>

int main(void) {
    FILE *fp = fopen("/home/user/memo.txt", "w");
    if (fp == NULL) {
        printf("書き込み用に開けませんでした\n");
        return 1;
    }
    fputs("Hello, file!\n", fp);
    fclose(fp);
    printf("書き込み完了\n");

    fp = fopen("/home/user/memo.txt", "r");
    if (fp == NULL) {
        printf("読み込み用に開けませんでした\n");
        return 1;
    }
    printf("読み込み結果: ");
    int c;
    while ((c = fgetc(fp)) != EOF) {
        putchar(c);
    }
    fclose(fp);

    FILE *missing = fopen("/home/user/nothing.txt", "r");
    if (missing == NULL) {
        printf("存在しないファイルなのでNULLが返りました\n");
    } else {
        fclose(missing);
    }
    return 0;
}

"a"(追記)モードは、実行するたびにファイルの末尾へ書き足していきます。

#include <stdio.h>

int main(void) {
    FILE *fp = fopen("/home/user/log.txt", "a");
    fputs("追記した行\n", fp);
    fclose(fp);
    printf("追記しました(実行するたびに1行ずつ増えます)\n");
    return 0;
}

やってみよう

上のコードを実行して、書き込み・読み込みができていることを確認しましょう。2番目のコードを何度か実行すると、追記されて増えていくことも確かめてみてください。また、fopen のモードを "r" に変えて、まだ存在しないファイル名を指定すると NULL チェックが発動する様子も試してみましょう。

演習

/home/user/greeting.txt"Konnichiwa!\n" という文字列を書き込んでから、同じファイルを読み込んで表示するプログラムを書いてください。書き込み用に開けなかった場合は「エラー」と表示してください。

ヒント1を見る

FILE *fp = fopen("/home/user/greeting.txt", "w"); で開き、fputs("Konnichiwa!\n", fp); で書き込みます。

ヒント2を見る

書き込んだら fclose で閉じ、もう一度 "r" で開いて fgetcループwhile ((c = fgetc(fp)) != EOF) putchar(c);)で読み出します。

実際に動かしてみよう

下のエディタにCを書いて「コンパイル & 実行」を押すと、ブラウザ内で本物のCコンパイラ(clang + dlmalloc)がその場でコンパイルして実行し、出力が表示されます。構造体・共用体・malloc/free・関数ポインタ・ファイル入出力などがそのまま動きます。本文の例を書き換えて試しながら進めましょう(初回だけコンパイラの読み込みに時間がかかります。以降はキャッシュされます。この回は標準入力(scanf)は使わず、値はコードに直接書きます)。

C/C++ — ブラウザ内で本物のコンパイラで実行

ブラウザ内で本物のC/C++コンパイラ(clang + libc++ / WebAssembly)を動かします。構造体・malloc/free・std::string・vector・クラス・テンプレート・STL などがそのまま実行できます(初回のみコンパイラの読み込みに時間がかかります。以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。