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::setwstd::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
  • 状态管理:随时检查 eoffail 等状态,保证健壮性。

掌握这些,便能在 C++ 中灵活、高效、安全地完成各种文件和流相关的 I/O 操作。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注