C++: ファイル操作応用

最終更新:2026-08-31

レッスン40では、例外処理について学びました。

ここでは、ファイルについて学びます——プログラマの必須スキルです。

ファイル、データベース、設定ファイルなど、ファイル操作は不可欠です。


1. ファイルストリーム

(1) 1.1 ファイルストリームクラス

C++はクラスでファイルを操作します:

クラス 機能
std::ifstream 入力ファイルストリーム(読み取り)
std::ofstream 出力ファイルストリーム(書き込み)
std::fstream 入出力ファイルストリーム(読み書き)

(2) 1.2 ファイルを開く

▶ サンプル 2:ファイルを開く(難易度 ⭐)

TEXT 📖 参照専用
#include <iostream>
#include <fstream>

int main() {
    std::ifstream file("data.txt");
    
    if (!file) {
        std::cerr << "ファイルを開けません" << std::endl;
        return 1;
    }
    
    std::cout << "ファイルを開きました" << std::endl;
    file.close();
    
    return 0;
}



2. ファイルの読み書き

(1) 2.1 行単位で読む

▶ サンプル:ファイルを開く(難易度 ⭐)

CPP
#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::ifstream file("data.txt");
    std::string line;
    int count = 0;
    
    while (std::getline(file, line)) {
        count++;
    }
    
    std::cout << "行数:" << count << std::endl;
    file.close();
    
    return 0;
}
▶ 試してみよう

(2) 2.2 書式付き入出力

▶ サンプル:構造体の書き込み(難易度 ⭐⭐)

CPP
#include <iostream>
#include <fstream>

struct Student {
    char name[50];
    int age;
    double score;
};

int main() {
    Student s = {"田中太郎", 20, 85.5};
    
    // 書き込み
    std::ofstream out("student.txt");
    out << s.name << std::endl;
    out << s.age << std::endl;
    out << s.score << std::endl;
    out.close();
    
    // 読み取り
    Student s2;
    std::ifstream in("student.txt");
    in >> s2.name >> s2.age >> s2.score;
    in.close();
    
    std::cout << "名前:" << s2.name << std::endl;
    std::cout << "年齢:" << s2.age << std::endl;
    std::cout << "スコア:" << s2.score << std::endl;
    
    return 0;
}
▶ 試してみよう
⚠️ 注意:

  • 書式付き入力は空白で区切られるため、注意が必要(>> 演算子の仕様)



3. バイナリファイル

(1) 3.1 なぜバイナリファイル?

特徴 テキストファイル バイナリファイル
可読性 人間が読める 機械向け
サイズ 大きい 小さい
精度 変換で精度損失 精度維持
移植性 高い (エンディアン問題あり)

(2) 3.2 バイナリ書き込み

▶ サンプル:構造体のバイナリ書き込み(難易度 ⭐⭐⭐)

CPP
#include <iostream>
#include <fstream>

struct Student {
    char name[50];
    int age;
    double score;
};

int main() {
    Student s = {"田中太郎", 20, 85.5};
    
    // バイナリ書き込み
    std::ofstream out("student.bin", std::ios::binary);
    out.write(reinterpret_cast<char*>(&s), sizeof(s));
    out.close();
    
    // バイナリ読み取り
    Student s2;
    std::ifstream in("student.bin", std::ios::binary);
    in.read(reinterpret_cast<char*>(&s2), sizeof(s2));
    in.close();
    
    std::cout << "名前:" << s2.name << std::endl;
    std::cout << "年齢:" << s2.age << std::endl;
    std::cout << "スコア:" << s2.score << std::endl;
    
    return 0;
}
▶ 試してみよう
💡 ヒント:

  • バイナリ入出力には writeread を使用
  • データサイズを正確に管理(sizeof



4. 4. ランダムアクセス

(1) 4.1 seekgとseekp

ファイルの読み取り位置書き込み位置を移動します。

関数 機能
seekg(pos) 読み取り位置を設定
seekp(pos) 書き込み位置を設定
tellg() 現在の読み取り位置を取得
tellp() 現在の書き込み位置を取得

(2) 4.2 例:ファイルの特定位置を変更(難易度 ⭐⭐⭐)

CPP
#include <iostream>
#include <fstream>

int main() {
    std::fstream file("data.txt", std::ios::in | std::ios::out);
    
    // 10バイト目に移動
    file.seekp(10);
    
    // そこに書き込み(上書き)
    file << "Hello";
    
    file.close();
    return 0;
}



5. ファイルストリームの状態

(1) 5.1 状態関数

ファイルストリームには4つの状態関数があります:

関数 説明
good() 正常
eof() ファイル終端に到達
fail() エラー(型不一致など)
bad() 重大なエラー(ストリーム破損)

(2) 5.2 状態の確認

▶ サンプル:ファイル終端の検出(難易度 ⭐)

CPP
#include <iostream>
#include <fstream>

int main() {
    std::ifstream file("data.txt");
    std::string line;
    
    while (true) {
        std::getline(file, line);
        
        if (file.eof()) {
            break; // 終端に到達
        }
        
        std::cout << line << std::endl;
    }
    
    file.clear(); // 状態をクリア
    file.close();
    
    return 0;
}
▶ 試してみよう


6. 実践:簡易データベース

▶ サンプル 1:学生記録管理(難易度 ⭐⭐⭐)

TEXT 📖 参照専用
#include <iostream>
#include <fstream>
#include <vector>
#include <string>

struct Student {
    int id;
    char name[50];
    int age;
};

void saveStudents(const std::vector<Student>& students, const std::string& filename) {
    std::ofstream file(filename, std::ios::binary);
    for (const auto& s : students) {
        file.write(reinterpret_cast<const char*>(&s), sizeof(s));
    }
}

void loadStudents(std::vector<Student>& students, const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    Student s;
    while (file.read(reinterpret_cast<char*>(&s), sizeof(s))) {
        students.push_back(s);
    }
}

int main() {
    std::vector<Student> students = {
        {1, "田中太郎", 20},
        {2, "佐藤花子", 21}
    };
    
    // 保存
    saveStudents(students, "students.bin");
    
    // 読み取り
    std::vector<Student> loaded;
    loadStudents(loaded, "students.bin");
    
    std::cout << "読み取り完了:" << loaded.size() << "件のデータ" << std::endl;
    
    return 0;
}

▶ サンプル 3:ファイルへの追記(難易度 ⭐⭐)

CPP
#include <iostream>
#include <fstream>
#include <string>

int main() {
    // 追記モードでファイルを開く
    std::ofstream outFile("log.txt", std::ios::app);

    if (!outFile) {
        std::cerr << "追記用にファイルを開けません" << std::endl;
        return 1;
    }

    // 複数行を追記
    outFile << "ログエントリ 1: プログラム開始" << std::endl;
    outFile << "ログエントリ 2: データ処理中" << std::endl;
    outFile << "ログエントリ 3: プログラム終了" << std::endl;

    outFile.close();

    // ファイル全体を読む
    std::ifstream inFile("log.txt");
    std::string line;

    std::cout << "ファイル内容:" << std::endl;
    while (std::getline(inFile, line)) {
        std::cout << line << std::endl;
    }

    inFile.close();
    return 0;
}
▶ 試してみよう

出力:

TEXT 📖 参照専用
ファイル内容:
ログエントリ 1: プログラム開始
ログエントリ 2: データ処理中
ログエントリ 3: プログラム終了

❓ よくある質問

Q:テキストファイルとバイナリファイルの使い分けは? A: 可読性が必要 → テキストファイル - パフォーマンス/サイズ優先 → バイナリファイル - 移植性優先 → テキストファイル


Q:文字コードは? A: C++標準は文字コードを規定しません。対策:- UTF-8でファイルを保存 - 変換ライブラリを使用(iconvなど) - プラットフォーム固有のAPIを使用


Q:ファイルオープン失敗の対処は? A: if (!file) でチェック、例外処理で対処。


📖 まとめ

トピック 要点
ファイルストリームクラス ifstream/ofstream/fstream
テキストファイル <<>> で入出力
バイナリファイル writeread で入出力
ランダムアクセス seekg/seekp で位置移動
状態確認 eof()/fail()/bad()

📝 練習問題

  1. 初級(難易度 ⭐): ofstream でファイルに「Hello World」を書き込み、ifstream で読み込んで出力してください。

  2. 中級(難易度 ⭐⭐): fstreamios::binary でバイナリファイルを扱い、構造体配列を書き込み、読み込んでください。

  3. 上級(難易度 ⭐⭐⭐): seekg/tellg でファイルサイズを取得する機能を実装してください。「ファイルブラウザ」のような機能を作り、ファイルの特定位置からデータを読み込んでください。



次のレッスン:正規表現(#42)

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%