目录
一、文件 IO 的基本概念
C++ 中的文件 IO(输入/输出)操作主要通过 ifstream
(输入文件流)和 ofstream
(输出文件流)实现,它们分别用于从文件读取数据和向文件写入数据。
ifstream
:从文件读取数据(输入流)。ofstream
:向文件写入数据(输出流)。fstream
:支持同时读取和写入文件(双向流)。
头文件:#include <fstream>
继承关系:ifstream
继承自 istream
,ofstream
继承自 ostream
,fstream
继承自 iostream
。
二、文件流的基本操作
1. 打开文件
可以通过以下两种方式打开文件:
- 构造函数直接打开:
std::ifstream ifs("example.txt"); // 以只读模式打开文件 std::ofstream ofs("output.txt"); // 以写入模式打开文件
- 使用
open()
方法:std::ifstream ifs; ifs.open("example.txt"); // 以默认模式打开文件
2. 关闭文件
文件操作完成后需调用 close()
方法释放资源:
ifs.close(); // 关闭输入流
ofs.close(); // 关闭输出流
3. 检查文件是否成功打开
使用 is_open()
方法检查文件是否成功打开:
if (!ifs.is_open()) {
std::cerr << "文件打开失败!" << std::endl;
}
三、文本文件的读写操作
1. 写入文本文件(ofstream)
使用 <<
插入器向文件写入数据:
#include <fstream>
#include <iostream>
int main() {
std::ofstream ofs("output.txt");
if (!ofs) {
std::cerr << "无法创建文件!" << std::endl;
return 1;
}
ofs << "Hello, World!" << std::endl;
ofs << "This is a test." << std::endl;
ofs.close();
return 0;
}
2. 读取文本文件(ifstream)
使用 >>
提取器或 getline()
逐行读取数据:
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::ifstream ifs("output.txt");
if (!ifs) {
std::cerr << "文件不存在!" << std::endl;
return 1;
}
std::string line;
while (std::getline(ifs, line)) {
std::cout << line << std::endl;
}
ifs.close();
return 0;
}
四、二进制文件的读写操作
1. 写入二进制文件
使用 write()
方法以二进制格式写入数据:
#include <fstream>
#include <iostream>
struct Data {
int id;
double value;
};
int main() {
Data data = {1, 3.14};
std::ofstream ofs("binary.dat", std::ios::binary); // 以二进制模式打开
if (!ofs) {
std::cerr << "无法创建二进制文件!" << std::endl;
return 1;
}
ofs.write(reinterpret_cast<char*>(&data), sizeof(data)); // 写入结构体
ofs.close();
return 0;
}
2. 读取二进制文件
使用 read()
方法以二进制格式读取数据:
#include <fstream>
#include <iostream>
struct Data {
int id;
double value;
};
int main() {
Data data;
std::ifstream ifs("binary.dat", std::ios::binary); // 以二进制模式打开
if (!ifs) {
std::cerr << "无法读取二进制文件!" << std::endl;
return 1;
}
ifs.read(reinterpret_cast<char*>(&data), sizeof(data)); // 读取结构体
ifs.close();
std::cout << "ID: " << data.id << ", Value: " << data.value << std::endl;
return 0;
}
五、文件打开模式
模式 | 描述 |
---|---|
std::ios::in |
以读取模式打开文件(默认用于 ifstream )。 |
std::ios::out |
以写入模式打开文件(默认用于 ofstream )。 |
std::ios::app |
追加模式,在文件末尾写入内容。 |
std::ios::binary |
以二进制模式打开文件(默认是文本模式)。 |
std::ios::trunc |
如果文件存在,则清空内容(默认用于 ofstream )。 |
std::ios::ate |
打开文件后立即将文件指针定位到文件末尾。 |
组合模式示例:
std::ofstream ofs("log.txt", std::ios::out | std::ios::app); // 追加写入
六、异常处理与文件 IO
文件操作可能因文件不存在、权限不足等原因失败,需结合异常处理:
#include <fstream>
#include <iostream>
#include <stdexcept>
int main() {
try {
std::ifstream ifs("missing.txt");
if (!ifs) {
throw std::runtime_error("文件打开失败!");
}
// 读取文件...
} catch (const std::exception& e) {
std::cerr << "异常: " << e.what() << std::endl;
}
return 0;
}
七、常见错误与调试技巧
文件路径问题
- 相对路径:相对于当前工作目录(通常为项目根目录)。
- 绝对路径:如
"C:/Users/YourName/Desktop/file.txt"
。 - 解决方法:检查文件是否存在,或使用
std::filesystem::absolute()
获取绝对路径(C++17 起)。
文件权限问题
- 确保程序有权限读取/写入目标文件(如修改文件属性或运行程序时以管理员权限启动)。
二进制文件读写不一致
- 二进制写入和读取必须使用相同的模式(如
std::ios::binary
),否则可能导致数据损坏。
- 二进制写入和读取必须使用相同的模式(如
调试工具
- 使用
std::cerr
输出错误信息。 - 使用
Valgrind
检测内存泄漏。 - 使用
GDB
或 IDE 调试器逐步执行代码。
- 使用
八、完整示例
1. 文本文件的读写
#include <fstream>
#include <iostream>
#include <string>
int main() {
// 写入文件
std::ofstream ofs("example.txt");
if (ofs) {
ofs << "C++ 文件 IO 示例" << std::endl;
ofs << "这是第二行内容。" << std::endl;
ofs.close();
}
// 读取文件
std::ifstream ifs("example.txt");
if (ifs) {
std::string line;
while (std::getline(ifs, line)) {
std::cout << line << std::endl;
}
ifs.close();
}
return 0;
}
2. 二进制文件的读写
#include <fstream>
#include <iostream>
struct Student {
int id;
std::string name;
};
int main() {
Student student = {101, "Alice"};
std::ofstream ofs("students.dat", std::ios::binary);
if (ofs) {
ofs.write(reinterpret_cast<char*>(&student), sizeof(Student));
ofs.close();
}
Student readStudent;
std::ifstream ifs("students.dat", std::ios::binary);
if (ifs) {
ifs.read(reinterpret_cast<char*>(&readStudent), sizeof(Student));
ifs.close();
std::cout << "ID: " << readStudent.id << ", Name: " << readStudent.name << std::endl;
}
return 0;
}
九、总结
通过 ifstream
和 ofstream
,可以高效地实现 C++ 中的文件读写操作。关键点包括:
- 正确使用文件模式(如
std::ios::binary
、std::ios::app
)。 - 检查文件是否成功打开(
is_open()
)。 - 结合异常处理(
try/catch
)确保程序健壮性。 - 区分文本和二进制文件的读写方式。
- 调试文件路径和权限问题,避免因环境问题导致失败。