在 C++ 中,所有 I/O(输入/输出)都建立在 流(stream)之上——一种对数据源(文件、内存、网络等)进行统一抽象的双向管道。下面主要介绍文件流与常见的流类型,以及如何使用它们进行文本和二进制文件的读写。
1. 基础概念
std::istream/std::ostreamistream(输入流)提供提取操作operator>>、getline()等。ostream(输出流)提供插入操作operator<<、write()等。- 常见实例:
std::cin(标准输入,istream)、std::cout(标准输出,ostream)、std::cerr(标准错误,未缓冲)。
- 文件流(fstream)
定义于<fstream>,继承自istream/ostream:std::ifstream:输入文件流(读),派生自istreamstd::ofstream:输出文件流(写),派生自ostreamstd::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 操作。