6日でできる 新C言語入門|C言語のファイル操作入門

画面に表示するだけで終わらせず、データをファイルに残そう。
C言語のファイル操作を学ぶと、保存・読み込み・ログ出力ができる実用的なプログラムに近づきます。

C言語では、画面に文字を表示したり、キーボードから入力を受け取ったりするだけでなく、ファイルにデータを書き込んだり、ファイルからデータを読み込んだりできます。

ファイル操作を使えるようになると、プログラムの実用性が大きく広がります。たとえば、計算結果をテキストファイルに保存したり、外部ファイルに書かれた設定を読み込んだり、実行中の記録をログとして残したりできます。

テキストファイルの操作では、基本的に次の流れを使います。

まず、fopenでファイルを開きます。
次に、fprintf、fgets、fgetcなどを使って、書き込みや読み込みを行います。
最後に、fcloseでファイルを閉じます。

この流れはとても大切です。ファイルを開いたまま閉じ忘れると、書き込み内容が正しく保存されなかったり、不要なリソースを使い続けたりする可能性があります。

この記事では、テキストファイルへの書き込み、1行ずつの読み込み、1文字ずつの読み込み、FILE*の役割、fopenのモードの違いまで、サンプルプログラムを使ってやさしく解説していきます。

ファイル操作の基本の流れ

C言語でファイルを扱うときは、いきなり読み書きをするのではなく、まずファイルを開く必要があります。

ファイル操作の基本は、次の3段階です。

手順内容主に使う関数
1ファイルを開くfopen
2ファイルへ書き込む、または読み込むfprintf、fgets、fgetcなど
3ファイルを閉じるfclose

ファイルを開くと、FILE*型のファイルポインタが得られます。
このファイルポインタを使って、どのファイルに対して読み書きするのかを指定します。

たとえば、テキストファイルへ書き込む場合は、次のような流れになります。

FILE* fp = fopen("worklog.txt", "w");
fprintf(fp, "ファイルへ書き込みます。\n");
fclose(fp);

fopenでファイルを開き、fprintfで書き込み、fcloseで閉じています。

この3つの流れを最初にしっかり覚えておくと、ファイル操作全体を理解しやすくなります。

図:ファイル操作は開く・使う・閉じるの流れで考える

この図から分かること

この図から分かるのは、C言語のファイル操作は、ファイルを開く、読み書きする、閉じるという順番で進むということです。

fopenでファイルを開くと、FILE*型のファイルポインタを受け取ります。以降の書き込みや読み込みは、このファイルポインタを通して行います。処理が終わったら、fcloseでファイルを閉じることが大切です。

FILE*はファイルを操作するための入口

C言語でファイルを扱うときには、FILE*型の変数を使います。

FILE* fp;

FILEは、開いたファイルを操作するための情報を持つポインタです。
ファイル名そのものを毎回使って読み書きするのではなく、fopenで開いた結果として得られるFILE
を使います。

項目意味
FILE*ファイル操作に使うポインタ型
fpファイルポインタ変数としてよく使われる名前
fopenの戻り値ファイルを開けた場合はFILE*、失敗した場合はNULL
fprintfやfgetsの引数どのファイルを対象にするかをFILE*で指定する

ファイル操作では、fopenの結果がNULLかどうかを確認することがとても重要です。

ファイルが開けない原因には、ファイル名の間違い、保存先の権限不足、読み込み対象ファイルが存在しないなどがあります。

そのため、fopenのあとには必ずNULLチェックを入れる習慣をつけましょう。

if (fp == NULL) {
    printf("ファイルを開けません。\n");
    return 1;
}

テキストファイルへ書き込む

テキストファイルへ書き込むには、fopenで書き込みモードを指定してファイルを開きます。

書き込みにはfprintfを使います。fprintfはprintfに似ていますが、出力先が画面ではなくファイルになります。

関数主な役割
fopenファイルを開く
fprintf書式を指定してファイルに書き込む
fcloseファイルを閉じる

書き込みモードでは、代表的にwを使います。

wで開くと、ファイルが存在しない場合は新しく作成されます。すでに同じ名前のファイルがある場合は、内容が上書きされます。

そのため、既存の内容を残したい場合は注意が必要です。

テキストファイルへ日報を書き込むプログラム

次のプログラムでは、worklog.txtというテキストファイルを作成し、作業メモを2行書き込みます。

プロジェクト/ファイル名: Lesson67_1/main.c

#include <stdio.h>

int main(void) {
    FILE* fp = fopen("worklog.txt", "w");

    // ファイルを開けなかった場合はエラーメッセージを表示する
    if (fp == NULL) {
        printf("ファイルを開けません。\n");
        return 1;
    }

    // テキストファイルへ文字列を書き込む
    fprintf(fp, "今日の作業内容を記録します。\n");
    fprintf(fp, "C言語でテキストファイル操作を練習しました。\n");

    // 開いたファイルは最後に閉じる
    fclose(fp);

    return 0;
}

実行後のworklog.txtの内容

今日の作業内容を記録します。
C言語でテキストファイル操作を練習しました。

このプログラムでは、まずfopenでworklog.txtを開いています。

FILE* fp = fopen("worklog.txt", "w");

第1引数はファイル名です。
第2引数はモードです。ここではwを指定しているため、書き込み用としてファイルを開きます。

ファイルが正しく開けなかった場合、fopenはNULLを返します。

if (fp == NULL) {
    printf("ファイルを開けません。\n");
    return 1;
}

ファイルを開けた場合は、fprintfでファイルへ書き込みます。

fprintf(fp, "今日の作業内容を記録します。\n");

fprintfの第1引数にfpを指定することで、画面ではなくファイルへ出力できます。

最後にfcloseでファイルを閉じています。

fclose(fp);

ファイル操作では、開いたファイルを閉じるところまでをセットで考えましょう。

fopenのモードを使い分ける

fopenでは、ファイルをどのように開くかをモードで指定します。

モード意味ファイルがない場合
r読み込みエラー
w書き込み新規作成
a追記新規作成
r+読み込みと書き込みエラー
w+書き込みと読み込み新規作成
a+追記と読み込み新規作成

特に最初に覚えたいのは、r、w、aです。

モード使う場面
r既存のファイルを読みたい
w新しく書き込みたい、または上書きしたい
a既存の内容の末尾に追加したい

wは上書きモードです。
同じ名前のファイルがすでにある場合、その内容は消えて新しい内容になります。

aは追記モードです。
既存の内容を残したまま、末尾に新しい内容を追加します。

書き込み時に注意したいこと

ファイルへの書き込みでは、次の点に注意しましょう。

wは上書きになる

wで開くと、同じ名前のファイルがある場合に内容が上書きされます。
大切なファイルを扱うときは、ファイル名やモードをよく確認しましょう。

fcloseを忘れない

書き込み後にfcloseを忘れると、内容が正しく保存されない可能性があります。

プログラムが終了すると自動的に閉じられる場合もありますが、学習段階からfcloseを書く習慣をつけることが大切です。

fopenの失敗を確認する

ファイルが開けなかったのにfprintfを使うと危険です。
必ずfpがNULLでないことを確認してから読み書きしましょう。

テキストファイルを1行ずつ読み込む

ファイルから1行ずつ読み込みたい場合は、fgetsを使います。

fgetsは、指定した配列に1行分の文字列を読み込みます。

関数主な役割
fgetsファイルから1行ずつ文字列を読み込む
fopen読み込みモードでファイルを開く
fclose読み込みが終わったファイルを閉じる

fgetsは、読み込みに成功すると文字列を返し、読み込むものがなくなるとNULLを返します。

そのため、while文と組み合わせることで、ファイルの終わりまで1行ずつ読み込めます。

while (fgets(line, sizeof(line), fp) != NULL) {
    printf("%s", line);
}

ここでlineは、読み込んだ1行を保存するためのchar配列です。

図:fgetsでテキストファイルを1行ずつ読み込む

この図から分かること

この図から分かるのは、fgetsがファイルの内容を1行ずつ読み込み、用意した文字配列へ保存するということです。

1回のfgetsで1行分を読み込み、while文で繰り返すことで、ファイルの最後まで順番に処理できます。行単位で処理したいログファイルや設定ファイルの読み込みに向いています。

1行ずつ読み込んで表示するプログラム

次のプログラムでは、worklog.txtを読み込みモードで開き、1行ずつ画面へ表示します。

プロジェクト/ファイル名: Lesson67_2/main.c

#include <stdio.h>

int main(void) {
    FILE* fp = fopen("worklog.txt", "r");
    char line[256];

    // ファイルを開けなかった場合はエラーメッセージを表示する
    if (fp == NULL) {
        printf("ファイルを開けません。\n");
        return 1;
    }

    // ファイルの内容を1行ずつ読み込んで表示する
    while (fgets(line, sizeof(line), fp) != NULL) {
        printf("%s", line);
    }

    // 読み込みが終わったらファイルを閉じる
    fclose(fp);

    return 0;
}

実行結果

今日の作業内容を記録します。
C言語でテキストファイル操作を練習しました。

このプログラムを実行するには、読み込み対象のworklog.txtが実行時の作業フォルダーに存在している必要があります。

Visual Studioで学習している場合は、Lesson67_1で作成したworklog.txtを、Lesson67_2の実行時に読み込める場所へコピーしておくと確認しやすいです。

このプログラムでは、fopenでworklog.txtを読み込みモードで開いています。

FILE* fp = fopen("worklog.txt", "r");

rは読み込みモードです。
ファイルが存在しない場合、fopenはNULLを返します。

fgetsでは、line配列へ1行ずつ読み込んでいます。

fgets(line, sizeof(line), fp)

sizeof(line)を指定しているため、line配列のサイズを超えない範囲で読み込めます。

fgetsで読み込むときのポイント

fgetsを使うときは、読み込み先の配列とサイズを指定します。

fgets(line, sizeof(line), fp)
引数意味
line読み込んだ文字列を保存する配列
sizeof(line)読み込み可能な最大サイズ
fp読み込み対象のファイルポインタ

fgetsは、改行文字も読み込む場合があります。
そのため、printfで表示するときは、printf("%s", line);のように、余計な改行を追加しない形にすると自然に表示できます。

また、1行が配列サイズより長い場合は、途中まで読み込まれます。
長い行を扱う場合は、バッファサイズや読み込み処理を工夫する必要があります。

テキストファイルを1文字ずつ読み込む

ファイルを1文字ずつ読み込みたい場合は、fgetcを使います。

fgetcは、ファイルから1文字を読み込みます。

関数主な役割
fgetcファイルから1文字ずつ読み込む
EOFファイルの終わりを表す値
fclose読み込み後にファイルを閉じる

fgetcの戻り値はint型です。
char型ではなくint型で受け取る点が重要です。

int ch;

ファイルの終わりに到達すると、fgetcはEOFを返します。

そのため、次のようにwhile文でEOFまで読み込みます。

while ((ch = fgetc(fp)) != EOF) {
    printf("%c", ch);
}

1文字単位で処理したい場合、たとえば文字数を数える、特定の文字を探す、文字ごとに変換する、といった処理に向いています。

1文字ずつ読み込んで表示するプログラム

次のプログラムでは、worklog.txtを1文字ずつ読み込み、そのまま画面に表示します。

プロジェクト/ファイル名: Lesson67_3/main.c

#include <stdio.h>

int main(void) {
    FILE* fp = fopen("worklog.txt", "r");
    int ch;

    // ファイルを開けなかった場合はエラーメッセージを表示する
    if (fp == NULL) {
        printf("ファイルを開けません。\n");
        return 1;
    }

    // ファイルの内容を1文字ずつ読み込んで表示する
    while ((ch = fgetc(fp)) != EOF) {
        printf("%c", ch);
    }

    // 読み込みが終わったらファイルを閉じる
    fclose(fp);

    return 0;
}

実行結果

今日の作業内容を記録します。
C言語でテキストファイル操作を練習しました。

このプログラムでも、worklog.txtが実行時に読み込める場所にある必要があります。

fgetcは、ファイルから1文字ずつ読み込みます。

ch = fgetc(fp)

読み込んだ文字をchに代入し、EOFでなければ表示しています。

printf("%c", ch);

fgetcの戻り値をint型で受け取る理由は、通常の文字とEOFを区別するためです。
EOFはファイルの終わりを表す特別な値なので、char型ではなくint型で受け取るのが基本です。

図:fgetsとfgetcの読み込み単位の違い

この図から分かること

この図から分かるのは、fgetsとfgetcでは読み込む単位が違うということです。

fgetsは1行ずつ読み込むため、行ごとの処理に向いています。fgetcは1文字ずつ読み込むため、文字数を数えたり、特定の文字を探したりする処理に向いています。目的に合わせて読み込み関数を選ぶことが大切です。

fgetsとfgetcの使い分け

テキストファイルを読み込むときは、どの単位で処理したいかによって関数を選びます。

読み込み方法使う関数向いている処理
1行ずつ読むfgetsログ、文章、設定ファイルの行単位処理
1文字ずつ読むfgetc文字数カウント、特定文字の検索、文字単位の変換

行単位でそのまま表示したい場合はfgetsが分かりやすいです。
文字ごとに細かく調べたい場合はfgetcが向いています。

どちらの場合も、ファイルを開いたら最後にfcloseで閉じることを忘れないようにしましょう。

読み込みと書き込みの関数を整理する

テキストファイル操作でよく使う関数を整理しておきましょう。

用途代表的な関数説明
ファイルを開くfopenファイル名とモードを指定して開く
書き込みfprintf書式を指定してファイルへ出力する
書き込みfputs文字列をファイルへ出力する
読み込みfgets1行ずつ読み込む
読み込みfgetc1文字ずつ読み込む
ファイルを閉じるfclose開いたファイルを閉じる

まずは、fopen、fprintf、fgets、fgetc、fcloseの基本を押さえると、テキストファイル操作の全体像が見えてきます。

ファイル操作でよくあるミス

ファイル操作では、次のようなミスに注意しましょう。

fopenのNULLチェックを忘れる

ファイルが開けなかった場合、fpはNULLになります。
そのままfprintf、fgets、fgetcを使うと危険です。

必ずNULLチェックを行いましょう。

if (fp == NULL) {
    printf("ファイルを開けません。\n");
    return 1;
}

fcloseを書き忘れる

ファイルを開いたら、使い終わったあとにfcloseで閉じます。
特に書き込みでは、fcloseを忘れると内容が正しく反映されないことがあります。

読み込み対象のファイルがない

rモードでは、ファイルが存在しないと開けません。
Lesson67_2やLesson67_3を実行するときは、worklog.txtが読み込める場所にあるか確認しましょう。

wで大切なファイルを上書きする

wモードは上書きです。
既存の内容を残したい場合は、aモードを使うことを検討します。

文字コードの違いで表示が崩れる

日本語を含むテキストファイルでは、文字コードによって表示が崩れることがあります。
Visual Studioや実行環境の文字コード設定によって見え方が変わる場合があるため、学習時は同じ環境で作成したファイルを読み込むと確認しやすくなります。

ファイル操作を使うとできることが広がる

ファイル操作を覚えると、C言語プログラムで扱えるデータの幅が広がります。

活用例内容
ログ出力実行中の記録をテキストファイルへ保存する
設定読み込み設定値をファイルから読み込む
結果保存計算結果や集計結果を保存する
データ入力外部ファイルに書かれたデータを処理する
簡易データベース複数行のテキストを保存して管理する

画面に表示するだけのプログラムでは、実行が終わると結果が残りません。
ファイルへ書き込めば、実行後にも結果を確認できます。

また、ファイルから読み込めば、毎回キーボードで入力しなくても、外部データを使って処理できます。

テキストファイル操作を安全に扱うために

テキストファイル操作では、次の流れをいつも意識しましょう。

手順確認すること
fopenファイル名とモードが正しいか
NULLチェックファイルを開けたか
読み書き目的に合った関数を使っているか
fclose最後にファイルを閉じているか

書き込みでは、fprintfを使うとprintfに近い感覚でファイルへ出力できます。
読み込みでは、1行ずつ処理したいならfgets、1文字ずつ処理したいならfgetcを使います。

この基本を押さえることで、C言語プログラムは画面の中だけで完結せず、ファイルを通してデータを保存したり再利用したりできるようになります。

テキストファイルの読み書きは、実用的なプログラムへ進むための大切な一歩です。まずはLesson67_1でファイルに書き込み、Lesson67_2とLesson67_3で読み込む流れを実際に動かしながら確認してみましょう。