高度なファイル操作
[第]40[課では]例外処理について学びました。
[現在]、[私たちは]ファイル[操作]――プログラムにおける[データを永続化するための核心的なスキル]――について深く掘り下げていきます。
[設定]ファイル、[ログ]、[あるいはデータベース]のいずれであっても、[ファイル][操作]なしには成り立ちません。
1. ファイルストリーム[概要]
(1) 1.1 [3つの]ファイルストリームクラス
C++で[3つの]クラスを使ってファイルを[処理]する:
| クラス | [機能] |
|---|---|
std::ifstream |
入力ファイルストリーム([読み込み]ファイル) |
std::ofstream |
出力ファイルストリーム([写]file) |
std::fstream |
入出力ファイルストリーム([読み書き]) |
(2) 1.2 [ファイルを開く]
例:[開く]ファイル (難易度 ⭐)
▶ サンプル 2: file[操作デモ] (難易度 ⭐)
CPP
#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 [フォーマットによる読み書き]
例:[読み書き]struct (難易度 ⭐⭐)
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 [なぜバイナリ形式のファイルを使うのか]?
| [比較] | [テキスト]ファイル | [バイナリ]ファイル |
|---|---|---|
| [可読性] | [人]class[可読] | [不可読] |
| [スペース] | [大きい] | [小さい] |
| [速度] | [遅い] | [速い] |
| [クロスプラットフォーム] | [良い] | [悪い]([バイト順の問題]) |
(2) 3.2 [バイナリファイルの読み書き]
例:[バイナリの読み書き]struct (難易度 ⭐⭐⭐)
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;
}
💡 ヒント:
- [バイナリ読み書き用]
write[および]read - [バイト数を指定する必要があります](
sizeof)
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: [学生記録管理] (難易度 ⭐⭐⭐)
CPP
#include iostream
#include fstream
#include vector
#include string
struct Student {
int id;
char name[50];
int age;
};
void saveStudents(const std::vectorStudent& 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::vectorStudent& 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::vectorStudent students = {
{1, "...", 20},
{2, "...", 21}
};
// ...
saveStudents(students, "students.bin");
// ...
std::vectorStudent loaded;
loadStudents(loaded, "students.bin");
std::cout << "..." << loaded.size() << "..." << std::endl;
return 0;
}
❓ よくある質問
Q [テキスト]ファイル[とバイナリ]ファイル[、どちらが良いですか]?
A [要件によります]: - [人間が]読み取れる[必要がある] → [テキスト]ファイル - [パフォーマンス]や[容量]を[重視する] → [バイナリ]ファイル - [クロスプラットフォーム対応]が必要 → [テキスト]ファイル
Q [中国語の文字はどう処理すればいいですか]?
A C++は[Unicodeへの対応が不十分]です。[以下の方法をお勧めします]: - [UTF-8エンコーディングでテキストファイルを保存する] - [サードパーティ製ライブラリ]([例:]iconv)を使用する - [あるいは、英語]または[ピンイン]のみを保存する
Q ファイルが開けない場合はどうすればよいですか?
A
if (!file) を使って確認し、例外処理を併用してください。📖 まとめ
| [知識ポイント] | [要点] |
|---|---|
| ファイルストリームクラス | ifstream/ofstream/fstream |
| [テキスト]ファイル | << [と] >> [演算子] |
| [バイナリ]ファイル | write [と] read |
| [ランダムアクセス] | seekg/seekp |
| [状態確認] | eof()/fail()/bad() |
📝 練習問題
-
**初心者(難易度 ⭐):[ofstream を使用して] [テキストファイル]([3行分の内容])に書き込み、[ifstream を使用して] [読み込んで] 画面に出力する。
-
**中級(難易度 ⭐⭐):[fstream] を使用し、[ios::binary] モードで [file] を開き、[structarray] を書き込み、[読み込んで検証] する。
-
**上級(難易度 ⭐⭐⭐):[使用] seekg/tellg [実装] file [ランダムアクセス]。[「インデックス」file を作成し、各レコードの位置を記録する]。[番号指定による指定レコードへの直接ジャンプをサポートする]。
- ファイルストリーム:ifstream [読み取り]/ofstream [書き込み]/fstream [読み書き]
- [モード]:in/out/app/binary/trunc
- file[状態チェック]:is_open/good/fail/eof
- [テキスト]ファイルと[バイナリ]ファイル:[テキストは読み込めるが処理に時間がかかる]
- [ランダムアクセス]:seekg/tellg [読み書き位置の指定]
[次のレッスン]:[正規表現](#42)



