C++ 的文件 I/O 与普通 I/O 工作原理非常相似,只是增加了少量细节。标准库提供了 3 个基本的文件 I/O 类:
ifstream
(派生自istream
)——用于文件输入;ofstream
(派生自ostream
)——用于## 文件输出;fstream
(派生自iostream
)——用于文件输入/输出。
使用这些类前需包含头文件 <fstream>
。
与 cout
、cin
、cerr
、clog
等已自动就绪的流不同,文件流必须由程序员显式建立。但过程极其简单:只需用文件名作为参数构造相应文件流对象,随后便可使用 <<
或 >>
进行读写。使用完毕后,可显式调用 close()
关闭文件;若忽略此步骤,当文件流对象离开作用域时,其析构函数会自动关闭文件。
文件输出
下面示例使用 ofstream
向文件写入数据:
#include <fstream>
#include <iostream>
int main()
{
// 使用 ofstream 写文件,文件名为 Sample.txt
std::ofstream outf{ "Sample.txt" };
// 若无法打开文件
if (!outf)
{
std::cerr << "Uh oh, Sample.txt could not be opened for writing!\n";
return 1;
}
// 写入两行
outf << "This is line 1\n";
outf << "This is line 2\n";
return 0;
// outf 离开作用域后,析构函数自动关闭文件
}
在项目目录下将生成 Sample.txt
,用文本编辑器打开即可看到两行内容。
也可使用 put()
一次写入单个字符。
文件输入
下面读取刚才创建的文件:
#include <fstream>
#include <iostream>
#include <string>
int main()
{
// 使用 ifstream 读文件
std::ifstream inf{ "Sample.txt" };
if (!inf)
{
std::cerr << "Uh oh, Sample.txt could not be opened for reading!\n";
return 1;
}
std::string strInput{};
while (inf >> strInput) // 提取运算符以空白为分隔
std::cout << strInput << '\n';
return 0;
// inf 离开作用域后析构,自动关闭文件
}
输出结果为:
This
is
line
1
This
is
line
2
显然,提取运算符遇到空白即分割。若想整行读取,应使用 getline()
:
std::string strInput{};
while (std::getline(inf, strInput))
std::cout << strInput << '\n';
输出:
This is line 1
This is line 2
缓冲输出
C++ 的输出可能是缓冲的。数据先写入缓冲区,而非立即落盘。当缓冲区被“刷新”(flush)时,才会真正写入磁盘。关闭文件会强制刷新缓冲区并关闭文件。
若程序异常终止或显式调用 exit()
而未关闭文件,缓冲区可能未刷新,导致数据丢失。因此,在调用 exit()
前应显式关闭文件。
可手动刷新:
- 调用
ostream::flush()
- 向流插入
std::flush
- 使用
std::endl
(会插入换行并刷新,但频繁使用可能影响性能;性能敏感场景可用'\n'
代替)
文件打开模式
默认情况下,若文件已存在,写操作会覆盖原有内容。如需追加,可在构造 ofstream
时指定模式:
模式标志 | 含义 |
---|---|
app | 追加模式:写入始终在文件末尾 |
ate | 打开后立即定位到文件尾 |
binary | 以二进制方式打开 |
in | 读模式(ifstream 默认) |
out | 写模式(ofstream 默认) |
trunc | 若文件已存在,先清空 |
可用按位或 |
组合多个标志。fstream
默认使用 std::ios::in | std::ios::out
;若文件不存在且仅用 in
模式,打开会失败。若需创建新文件,可仅用 out
模式。
示例:向已有文件追加两行:
#include <iostream>
#include <fstream>
int main()
{
std::ofstream outf{ "Sample.txt", std::ios::app };
if (!outf)
{
std::cerr << "Uh oh, Sample.txt could not be opened for writing!\n";
return 1;
}
outf << "This is line 3\n";
outf << "This is line 4\n";
return 0;
}
文件内容变为:
This is line 1
This is line 2
This is line 3
This is line 4
显式打开文件(open())
同显式关闭文件一样,也可使用 open()
成员函数:
std::ofstream outf{ "Sample.txt" };
outf << "This is line 1\n";
outf << "This is line 2\n";
outf.close(); // 显式关闭
// 追加
outf.open("Sample.txt", std::ios::app);
outf << "This is line 3\n";
outf.close();
更多 open()
细节可查阅官方文档。