C++: 文件操作进阶
最后更新:2026-08-26
第40课我们学了异常处理。
现在,我们要深入文件操作——程序持久化数据的核心技能。
无论是配置文件、日志、还是数据库,都离不开文件操作。
1. 文件流概述
(1) 1.1 三个文件流类
C++用三个类处理文件:
| 类 | 功能 |
|---|---|
std::ifstream |
输入文件流(读文件) |
std::ofstream |
输出文件流(写文件) |
std::fstream |
输入输出文件流(读写) |
(2) 1.2 打开文件
示例:打开文件(难度⭐)
▶ 示例 2:文件操作演示(难度⭐)
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;
}
输出:
TEXT
📖 仅展示
文件打开成功
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;
}
💡 提示:
- 二进制读写用
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;
}
输出:
TEXT
📖 仅展示
Hello, File!
C++ 文件操作
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::vector<Student> students = {
{1, "张三", 20},
{2, "李四", 21}
};
// 保存
saveStudents(students, "students.bin");
// 加载
std::vectorStudent loaded;
loadStudents(loaded, "students.bin");
std::cout << "加载了" << loaded.size() << "条记录" << std::endl;
return 0;
}
输出:
TEXT
📖 仅展示
加载了2条记录
▶ 示例 3:简单文件读写(难度⭐)
CPP
#include <iostream>
#include <fstream>
#include <string>
int main() {
// 写入文件
std::ofstream outFile("test.txt");
outFile << "Hello, File!" << std::endl;
outFile << "C++ 文件操作" << std::endl;
outFile.close();
// 读取文件
std::ifstream inFile("test.txt");
std::string line;
while (std::getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
return 0;
}
输出:
TEXT
📖 仅展示
(程序输出)
预期输出:
TEXT
📖 仅展示
Hello, File!
C++ 文件操作
❓ 常见问题
Q 文本文件和二进制文件哪个好?
A 看需求: - 需要人类可读 → 文本文件 - 需要性能/空间 → 二进制文件 - 需要跨平台 → 文本文件
Q 中文字符怎么处理?
A C++对Unicode支持不好,建议: - 用UTF-8编码保存文本文件 - 用第三方库(如iconv) - 或者只存英文/拼音
Q 文件打不开怎么办?
A 用
if (!file) 检查,配合异常处理。📖 小节
| 知识点 | 要点 |
|---|---|
| 文件流类 | ifstream/ofstream/fstream |
| 文本文件 | << 和 >> 操作符 |
| 二进制文件 | write 和 read |
| 随机访问 | seekg/seekp |
| 状态检查 | eof()/fail()/bad() |
📝 作业
-
**基础题 (Difficulty ⭐):用 ofstream 写入一个文本文件(三行内容),再用 ifstream 读取并输出到屏幕。
-
**进阶题 (Difficulty ⭐⭐):用 fstream 以 ios::binary 模式打开文件,写入一个结构体数组,再读取验证。
-
**挑战题 (Difficulty ⭐⭐⭐):用 seekg/tellg 实现文件随机访问。创建一个"索引文件"记录每条记录的位置,支持按序号直接跳转到指定记录。
- 文件流:ifstream 读/ofstream 写/fstream 读写
- 打开模式:in/out/app/binary/trunc
- 文件状态检测:is_open/good/fail/eof
- 文本文件 vs 二进制文件:文本可读但慢
- 随机访问:seekg/tellg 定位读写位置
下一课:正则表达式(#42)