C++ 文件和流
在 C++ 中,所有 I/O(输入/输出)都建立在 流(stream)之上——一种对数据源(文件、内存、网络等)进行统一抽象的双向管道。下面主要介绍文件流与常见的流类型,以及如何使用它们进行文本和二进制文件的读写。
1. 基础概念
std::istream
/std::ostream
istream
(输入流)提供提取操作operator>>
、getline()
等。ostream
(输出流)提供插入操作operator<<
、write()
等。- 常见实例:
std::cin
(标准输入,istream
)、std::cout
(标准输出,ostream
)、std::cerr
(标准错误,未缓冲)。
- 文件流(fstream)
定义于<fstream>
,继承自istream
/ostream
:std::ifstream
:输入文件流(读),派生自istream
std::ofstream
:输出文件流(写),派生自ostream
std::fstream
:读写文件流(双向),派生自两者
2. 打开与关闭文件
#include <fstream>
// 打开文本文件用于写入(覆盖模式)
std::ofstream ofs("example.txt");
if (!ofs) {
// 打开失败
}
// 打开文件追加写入
std::ofstream aos("log.txt", std::ios::app);
// 打开二进制读写
std::fstream fs("data.bin",
std::ios::in | std::ios::out | std::ios::binary);
// 用完后(或在析构时)自动关闭
ofs.close();
- 模式标志(可按位或组合):
std::ios::in
:读std::ios::out
:写(默认会截断原文件)std::ios::app
:所有写操作追加到末尾std::ios::binary
:二进制模式(不做换行或编码转换)std::ios::trunc
:打开即截断(常与out
一起)
3. 文本文件 I/O
3.1 写入
std::ofstream ofs("output.txt");
ofs << "Hello, World!" << '\n'
<< 123 << " " << 3.14 << std::endl;
- 支持所有
operator<<
重载(整型、浮点、字符串等);可用<iomanip>
中的格式控制(如std::setw
,std::setprecision
)。
3.2 读取
std::ifstream ifs("input.txt");
std::string line;
while (std::getline(ifs, line)) {
// 逐行读取,包括空格
process(line);
}
// 或者按空白分割读取
int x; double y;
ifs >> x >> y; // 遇空白自动分隔
getline
不会丢弃空行;operator>>
会跳过所有空白。
4. 二进制文件 I/O
二进制模式下,读写原始字节,不受换行或编码影响。
std::ofstream ofs("data.bin", std::ios::binary);
int n = 42;
double d = 3.14;
ofs.write(reinterpret_cast<const char*>(&n), sizeof n);
ofs.write(reinterpret_cast<const char*>(&d), sizeof d);
std::ifstream ifs("data.bin", std::ios::binary);
int n2;
double d2;
ifs.read(reinterpret_cast<char*>(&n2), sizeof n2);
ifs.read(reinterpret_cast<char*>(&d2), sizeof d2);
- 注意对齐与字节序:跨平台时需考虑 endianness 和结构体填充。
5. 自定义流与缓冲区
std::ostringstream
/std::istringstream
:基于std::string
的内存流,用于将文本“格式化”到字符串,或从字符串中解析。- 自定义
streambuf
:通过继承std::streambuf
可把流重定向到网络、压缩库等。
6. 错误与状态管理
每个流对象都有状态标志位,可通过以下方法查询和重置:
方法 | 含义 |
---|---|
eof() | 到达文件末尾 |
fail() | 读取/写入失败或格式错误 |
bad() | 严重 I/O 错误 |
good() | 无错误 |
clear() | 清除所有错误状态 |
if (ifs.fail()) { /* 处理输入错误 */ }
ifs.clear(); // 恢复状态
ifs.seekg(0); // 可重新定位读指针
小结
- 统一的流模型:用
istream
/ostream
抽象各种 I/O 目标。 - 文件流:通过
ifstream
/ofstream
/fstream
在文本和二进制模式下进行文件读写。 - 格式化与原始字节:文本用插入/提取运算符和
getline
,二进制用read
/write
。 - 状态管理:随时检查
eof
、fail
等状态,保证健壮性。
掌握这些,便能在 C++ 中灵活、高效、安全地完成各种文件和流相关的 I/O 操作。