基本概念
程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放
通过文件可以将数据持久化
C++中对文件操作需要包含头文件 <fstream>
文件类型分为两种:
- 文本文件 - 文件以文本的ASCII码形式存储在计算机中
- 二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们
操作文件的三大类:
1. ofstream:写操作
2. ifstream:读操作
3. fstream:读写操作
#include <fstream> // 必须包含的头文件
数据特性 | 说明 |
---|---|
程序运行时数据 | 临时数据,程序结束即释放 |
文件持久化数据 | 长期存储在磁盘中 |
文件打开模式
模式标志 | 功能描述 |
---|---|
ios::in | 为读取打开文件 |
ios::out | 为写入打开文件 |
ios::ate | 初始定位到文件末尾 |
ios::app | 追加写入模式 |
ios::trunc | 存在则清空重建 |
ios::binary | 二进制模式操作 |
文本文件
写文件
void test01() {// 1. 包含头文件(已在全局包含)// 2. 创建输出流对象ofstream ofs;// 3. 指定打开方式(组合模式用 | 连接)ofs.open("test.txt", ios::out | ios::trunc);// 4. 写入格式化数据ofs << "姓名:张三" << endl; // 正确使用<<运算符ofs << "性别:男" << endl;ofs << "年龄:18" << endl;// 5. 关闭文件流ofs.close();
}
读文件
基础操作框架
#include <fstream> // 必须包含的头文件
#include <string> // 字符串操作支持void readFileDemo() {// 1. 创建流对象ifstream ifs;// 2. 打开文件并验证ifs.open("test.txt", ios::in); // ios::in表示读取模式if (!ifs.is_open()) { // 必须检查打开状态cerr << "文件打开失败" << endl;return;}// 3. 读取数据(四种方式见下文)// 4. 关闭文件流ifs.close();
}
四种读取方式对比
方式1:运算符重载读取
char buf[1024] = {0}; // 1024为缓冲区长度
while (ifs >> buf) { // 自动处理空格/换行分隔cout << buf << endl;
}
特点:
- 自动按空白符分割内容
- 缓冲区需预分配固定大小
- 适合结构化数据读取
方式2:getline成员函数
char buf[1024] = {0};
while (ifs.getline(buf, sizeof(buf))) { // 流对象的成员函数cout << buf << endl; // 自动处理换行符
}
特点:
- 精确控制缓冲区大小
- 自动去除换行符
- 需注意缓冲区溢出风险
方式3:全局getline函数
string buf;
while (getline(ifs, buf)) { // 使用string自动管理内存cout << buf << endl; // 无长度限制
}
特点:
- 自动管理内存
- 无需担心缓冲区溢出
- 标准推荐方式
方式4:逐字符读取
char c;
while ((c = ifs.get()) != EOF) { // EOF检测cout << c; // 原样输出所有字符
}
特点:
- 完全控制读取过程
- 适合二进制文件处理
- 性能开销较大
二进制文件
核心操作框架
#include <fstream>
#include <string>// 示例数据结构
struct PlayerData {int id; // 4字节double score; // 8字节char name[32]; // 32字节
}; // 总大小:44字节void binaryDemo() {// 创建流对象fstream file("game.dat", ios::binary | ios::out | ios::in);// 验证文件状态if (!file.is_open()) {cerr << "文件打开失败" << endl;return;}// 读写操作(见下文示例)file.close();
}
读写文件
// 读取基本类型
int loadedScore;
file.read(reinterpret_cast<char*>(&loadedScore), sizeof(int));// 读取结构体(需内存对齐)
#pragma pack(push, 1) // 1字节对齐
struct PackedData {short type;bool valid;// ...
};
#pragma pack(pop)PackedData data;
file.read(reinterpret_cast<char*>(&data), sizeof(PackedData));// 批量读取
vector<PlayerData> players(10);
file.read(reinterpret_cast<char*>(players.data()), players.size() * sizeof(PlayerData));