[C言語] ファイルの読み込みと書き込み方法について解説

C言語でファイルの読み込みと書き込みを行うには、標準ライブラリのstdio.hを使用します。

ファイルを操作するためには、まずfopen関数でファイルを開きます。読み込みモードには\"r\"、書き込みモードには\"w\"を指定します。

ファイルからデータを読み込むにはfscanffgetsを、データを書き込むにはfprintffputsを使用します。

操作が終わったらfcloseでファイルを閉じることが重要です。

これにより、ファイルのリソースが解放され、データの整合性が保たれます。

この記事でわかること
  • テキストファイルとバイナリファイルの読み込み方法
  • ファイルへのデータ書き込みの基本
  • ファイルクローズの重要性とエラーハンドリングの方法
  • ファイルのコピー、検索と置換、分割と結合の応用例
  • よくある問題の原因と対処法

目次から探す

ファイルの読み込み

C言語でファイルを読み込む方法は、テキストファイルとバイナリファイルで異なります。

それぞれの方法を理解することで、効率的にデータを処理することができます。

テキストファイルの読み込み

テキストファイルの読み込みには、主にfgets関数fscanf関数を使用します。

fgets関数の使い方

fgets関数は、ファイルから1行ずつ文字列を読み込むために使用されます。

以下に基本的な使い方を示します。

#include <stdio.h>
int main() {
    FILE *file;
    char buffer[256]; // 読み込む文字列を格納するバッファ
    // ファイルを読み取りモードで開く
    file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルから1行ずつ読み込む
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer); // 読み込んだ行を出力
    }
    // ファイルを閉じる
    fclose(file);
    return 0;
}
ファイルの内容がそのまま出力されます。
例えば、example.txtに「こんにちは\n世界」と書かれていれば、プログラムはその内容をそのまま表示します。

fscanf関数の使い方

fscanf関数は、ファイルからフォーマットに従ってデータを読み込むために使用されます。

以下に基本的な使い方を示します。

#include <stdio.h>
int main() {
    FILE *file;
    int number;
    char word[50];
    // ファイルを読み取りモードで開く
    file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルから整数と文字列を読み込む
    while (fscanf(file, "%d %s", &number, word) != EOF) {
        printf("数値: %d, 単語: %s\n", number, word);
    }
    // ファイルを閉じる
    fclose(file);
    return 0;
}
data.txtに `123 apple\n456 banana` と書かれていれば、
プログラムは「数値: 123, 単語: apple」と「数値: 456, 単語: banana」を出力します。

バイナリファイルの読み込み

バイナリファイルの読み込みには、fread関数を使用します。

バイナリデータはテキストデータとは異なり、直接人間が読める形式ではないため、バッファの管理が重要です。

fread関数の使い方

fread関数は、バイナリファイルからデータを読み込むために使用されます。

以下に基本的な使い方を示します。

#include <stdio.h>
int main() {
    FILE *file;
    int buffer[10]; // 読み込むデータを格納するバッファ
    // ファイルをバイナリ読み取りモードで開く
    file = fopen("binary.dat", "rb");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルからデータを読み込む
    size_t bytesRead = fread(buffer, sizeof(int), 10, file);
    printf("読み込んだ要素数: %zu\n", bytesRead);
    // ファイルを閉じる
    fclose(file);
    return 0;
}
binary.datに10個の整数が保存されていれば、プログラムは「読み込んだ要素数: 10」と出力します。

バッファの管理

バイナリファイルを扱う際には、バッファの管理が重要です。

バッファサイズを適切に設定し、読み込むデータのサイズと一致させることで、データの破損を防ぎます。

また、fread関数の戻り値を確認し、実際に読み込まれたデータのサイズを把握することも重要です。

これにより、ファイルの終端に達したかどうかを判断できます。

ファイルの書き込み

C言語でファイルにデータを書き込む方法は、テキストファイルとバイナリファイルで異なります。

それぞれの方法を理解することで、データを正確に保存することができます。

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

テキストファイルへの書き込みには、主にfputs関数fprintf関数を使用します。

fputs関数の使い方

fputs関数は、文字列をファイルに書き込むために使用されます。

以下に基本的な使い方を示します。

#include <stdio.h>
int main() {
    FILE *file;
    // ファイルを書き込みモードで開く
    file = fopen("output.txt", "w");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルに文字列を書き込む
    fputs("こんにちは、世界!\n", file);
    // ファイルを閉じる
    fclose(file);
    return 0;
}
output.txtに「こんにちは、世界!」という文字列が書き込まれます。

fprintf関数の使い方

fprintf関数は、フォーマットに従ってデータをファイルに書き込むために使用されます。

以下に基本的な使い方を示します。

#include <stdio.h>
int main() {
    FILE *file;
    int number = 123;
    char word[] = "apple";
    // ファイルを書き込みモードで開く
    file = fopen("formatted_output.txt", "w");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルにフォーマットされたデータを書き込む
    fprintf(file, "数値: %d, 単語: %s\n", number, word);
    // ファイルを閉じる
    fclose(file);
    return 0;
}
formatted_output.txtに「数値: 123, 単語: apple」というフォーマットされた文字列が書き込まれます。

バイナリファイルへの書き込み

バイナリファイルへの書き込みには、fwrite関数を使用します。

バイナリデータはテキストデータとは異なり、直接人間が読める形式ではないため、データの整形が重要です。

fwrite関数の使い方

fwrite関数は、バイナリファイルにデータを書き込むために使用されます。

以下に基本的な使い方を示します。

#include <stdio.h>
int main() {
    FILE *file;
    int buffer[5] = {1, 2, 3, 4, 5}; // 書き込むデータ
    // ファイルをバイナリ書き込みモードで開く
    file = fopen("binary_output.dat", "wb");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルにデータを書き込む
    size_t elementsWritten = fwrite(buffer, sizeof(int), 5, file);
    printf("書き込んだ要素数: %zu\n", elementsWritten);
    // ファイルを閉じる
    fclose(file);
    return 0;
}
binary_output.datに5つの整数がバイナリ形式で書き込まれます。「書き込んだ要素数: 5」と出力されます。

データの整形と書き込み

バイナリファイルを扱う際には、データの整形が重要です。

データを適切な形式に変換し、バッファに格納してからfwrite関数を使用することで、データの破損を防ぎます。

また、fwrite関数の戻り値を確認し、実際に書き込まれたデータのサイズを把握することも重要です。

これにより、書き込みが成功したかどうかを判断できます。

ファイルのクローズとエラーハンドリング

ファイル操作を行う際には、ファイルのクローズとエラーハンドリングが重要です。

これにより、リソースの無駄遣いや予期しないエラーを防ぐことができます。

ファイルのクローズ

ファイルを使用した後は、必ずクローズすることが推奨されます。

これにより、ファイルハンドルが解放され、他のプロセスがファイルにアクセスできるようになります。

fclose関数の重要性

fclose関数は、開いたファイルを閉じるために使用されます。

ファイルを閉じることで、バッファに残っているデータがディスクに書き込まれ、リソースが解放されます。

#include <stdio.h>
int main() {
    FILE *file;
    // ファイルを開く
    file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルを閉じる
    if (fclose(file) != 0) {
        perror("ファイルを閉じる際にエラーが発生しました");
        return 1;
    }
    return 0;
}

クローズ時のエラーチェック

fclose関数は、ファイルを正常に閉じられた場合は0を返し、エラーが発生した場合はEOFを返します。

エラーチェックを行うことで、ファイルのクローズに失敗した場合の対処が可能になります。

エラーハンドリング

ファイル操作中にエラーが発生した場合、適切なエラーハンドリングを行うことが重要です。

これにより、プログラムの信頼性を向上させることができます。

perror関数の使い方

perror関数は、エラーメッセージを標準エラー出力に表示するために使用されます。

errnoの値に基づいて、エラーの詳細を出力します。

#include <stdio.h>
#include <errno.h>
int main() {
    FILE *file;
    // 存在しないファイルを開く
    file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    fclose(file);
    return 0;
}

errnoの活用法

errnoは、エラーが発生した際にエラーコードを格納するグローバル変数です。

errnoの値を確認することで、エラーの種類を特定し、適切な対処を行うことができます。

#include <stdio.h>
#include <errno.h>
int main() {
    FILE *file;
    // 存在しないファイルを開く
    file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        printf("エラーコード: %d\n", errno);
        perror("ファイルを開けません");
        return 1;
    }
    fclose(file);
    return 0;
}

errnoを活用することで、エラーの原因を特定し、ユーザーに対してより詳細なエラーメッセージを提供することが可能になります。

これにより、プログラムのデバッグが容易になり、ユーザーエクスペリエンスが向上します。

応用例

ファイル操作の基本を理解したら、応用例としてファイルのコピー、検索と置換、分割と結合を行う方法を学びましょう。

これらの操作は、データ処理やファイル管理において非常に役立ちます。

ファイルのコピー

ファイルのコピーは、元のファイルの内容を新しいファイルにそのまま複製する操作です。

テキストファイルのコピー方法

テキストファイルをコピーするには、fgetsfputsを組み合わせて使用します。

#include <stdio.h>
int main() {
    FILE *source, *destination;
    char buffer[256];
    // コピー元ファイルを開く
    source = fopen("source.txt", "r");
    if (source == NULL) {
        perror("コピー元ファイルを開けません");
        return 1;
    }
    // コピー先ファイルを開く
    destination = fopen("destination.txt", "w");
    if (destination == NULL) {
        perror("コピー先ファイルを開けません");
        fclose(source);
        return 1;
    }
    // ファイルを1行ずつコピー
    while (fgets(buffer, sizeof(buffer), source) != NULL) {
        fputs(buffer, destination);
    }
    // ファイルを閉じる
    fclose(source);
    fclose(destination);
    return 0;
}

バイナリファイルのコピー方法

バイナリファイルをコピーするには、freadfwriteを使用します。

#include <stdio.h>
int main() {
    FILE *source, *destination;
    char buffer[1024];
    size_t bytesRead;
    // コピー元ファイルをバイナリモードで開く
    source = fopen("source.dat", "rb");
    if (source == NULL) {
        perror("コピー元ファイルを開けません");
        return 1;
    }
    // コピー先ファイルをバイナリモードで開く
    destination = fopen("destination.dat", "wb");
    if (destination == NULL) {
        perror("コピー先ファイルを開けません");
        fclose(source);
        return 1;
    }
    // ファイルをバイナリ形式でコピー
    while ((bytesRead = fread(buffer, 1, sizeof(buffer), source)) > 0) {
        fwrite(buffer, 1, bytesRead, destination);
    }
    // ファイルを閉じる
    fclose(source);
    fclose(destination);
    return 0;
}

ファイルの検索と置換

ファイル内の特定の文字列を検索し、必要に応じて置換することができます。

テキストファイル内の文字列検索

テキストファイル内で文字列を検索するには、fgetsを使用して1行ずつ読み込み、strstr関数で検索します。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file;
    char buffer[256];
    const char *searchTerm = "検索文字列";
    // ファイルを開く
    file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイル内で文字列を検索
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        if (strstr(buffer, searchTerm) != NULL) {
            printf("見つかりました: %s", buffer);
        }
    }
    // ファイルを閉じる
    fclose(file);
    return 0;
}

文字列の置換方法

文字列を置換するには、検索した文字列を新しい文字列に置き換え、結果を新しいファイルに書き込みます。

#include <stdio.h>
#include <string.h>
void replaceString(char *str, const char *oldWord, const char *newWord) {
    char buffer[256];
    char *pos;
    int index = 0;
    int oldWordLen = strlen(oldWord);
    while ((pos = strstr(str, oldWord)) != NULL) {
        // 置換前の部分をコピー
        strncpy(buffer + index, str, pos - str);
        index += pos - str;
        // 新しい単語をコピー
        strcpy(buffer + index, newWord);
        index += strlen(newWord);
        // 残りの文字列をコピー
        str = pos + oldWordLen;
    }
    // 残りの文字列をコピー
    strcpy(buffer + index, str);
    strcpy(str, buffer);
}
int main() {
    FILE *source, *destination;
    char buffer[256];
    const char *oldWord = "古い単語";
    const char *newWord = "新しい単語";
    // コピー元ファイルを開く
    source = fopen("source.txt", "r");
    if (source == NULL) {
        perror("コピー元ファイルを開けません");
        return 1;
    }
    // コピー先ファイルを開く
    destination = fopen("destination.txt", "w");
    if (destination == NULL) {
        perror("コピー先ファイルを開けません");
        fclose(source);
        return 1;
    }
    // ファイルを1行ずつ読み込み、置換して書き込む
    while (fgets(buffer, sizeof(buffer), source) != NULL) {
        replaceString(buffer, oldWord, newWord);
        fputs(buffer, destination);
    }
    // ファイルを閉じる
    fclose(source);
    fclose(destination);
    return 0;
}

ファイルの分割と結合

大きなファイルを分割したり、複数のファイルを結合したりすることができます。

大きなファイルの分割方法

大きなファイルを分割するには、一定サイズごとに新しいファイルを作成し、データを書き込みます。

#include <stdio.h>
int main() {
    FILE *source, *part;
    char buffer[1024];
    size_t bytesRead;
    int partNumber = 1;
    char partName[20];
    // 分割するファイルをバイナリモードで開く
    source = fopen("largefile.dat", "rb");
    if (source == NULL) {
        perror("ファイルを開けません");
        return 1;
    }
    // ファイルを分割
    while ((bytesRead = fread(buffer, 1, sizeof(buffer), source)) > 0) {
        sprintf(partName, "part%d.dat", partNumber++);
        part = fopen(partName, "wb");
        if (part == NULL) {
            perror("分割ファイルを開けません");
            fclose(source);
            return 1;
        }
        fwrite(buffer, 1, bytesRead, part);
        fclose(part);
    }
    // ファイルを閉じる
    fclose(source);
    return 0;
}

複数ファイルの結合方法

複数のファイルを結合するには、各ファイルを順に読み込み、1つのファイルに書き込みます。

#include <stdio.h>
int main() {
    FILE *part, *destination;
    char buffer[1024];
    size_t bytesRead;
    int partNumber = 1;
    char partName[20];
    // 結合先ファイルをバイナリモードで開く
    destination = fopen("combined.dat", "wb");
    if (destination == NULL) {
        perror("結合先ファイルを開けません");
        return 1;
    }
    // 各分割ファイルを結合
    while (1) {
        sprintf(partName, "part%d.dat", partNumber++);
        part = fopen(partName, "rb");
        if (part == NULL) {
            break; // ファイルが存在しない場合、結合を終了
        }
        while ((bytesRead = fread(buffer, 1, sizeof(buffer), part)) > 0) {
            fwrite(buffer, 1, bytesRead, destination);
        }
        fclose(part);
    }
    // ファイルを閉じる
    fclose(destination);
    return 0;
}

これらの応用例を活用することで、ファイル操作の幅が広がり、より複雑なデータ処理が可能になります。

よくある質問

ファイルが開けないのはなぜ?

ファイルが開けない原因はさまざまです。

以下の点を確認してください。

  • ファイルパスの誤り: ファイルのパスが正しいか確認してください。

相対パスと絶対パスの違いにも注意が必要です。

  • ファイルの存在: 指定したファイルが存在するか確認してください。

特に、読み取りモードで開く場合は、ファイルが存在しないとエラーになります。

  • アクセス権限: ファイルに対する適切なアクセス権限があるか確認してください。

特に、書き込みモードで開く場合は、書き込み権限が必要です。

読み込みが途中で止まるのはなぜ?

ファイルの読み込みが途中で止まる原因として、以下の点が考えられます。

  • バッファサイズの不足: 読み込むデータがバッファサイズを超えている場合、データが途中で切れることがあります。

バッファサイズを適切に設定してください。

  • ファイルの終端: ファイルの終端に達した場合、読み込みが停止します。

fgetsfreadの戻り値を確認し、EOFに達したかどうかを判断してください。

  • エラーの発生: 読み込み中にエラーが発生した場合、処理が停止することがあります。

ferror関数を使用してエラーを確認してください。

書き込みが反映されないのはなぜ?

書き込みが反映されない原因として、以下の点が考えられます。

  • バッファリングの影響: 書き込みがバッファリングされている場合、fclosefflushを使用してバッファをフラッシュする必要があります。
  • ファイルのクローズ忘れ: ファイルを閉じていない場合、書き込みがディスクに反映されないことがあります。

必ずfcloseを呼び出してください。

  • エラーの発生: 書き込み中にエラーが発生した場合、データが正しく書き込まれないことがあります。

ferror関数を使用してエラーを確認してください。

まとめ

ファイルの読み書きはC言語プログラミングにおいて重要なスキルです。

この記事では、ファイルの読み込み、書き込み、クローズ、エラーハンドリング、そして応用例について詳しく解説しました。

これらの知識を活用することで、より高度なファイル操作が可能になります。

ぜひ、実際にコードを書いて試してみてください。

  • URLをコピーしました!
目次から探す