[C++高频精进] 文件IO:文件流

核心要点速览

  • 3 类流:ifstream(读)、ofstream(写)、fstream(读写),继承自istream/ostream/iostream,复用>>/<<
  • 5 种模式:in(读)、out(写 + 截断)、app(追加)、ate(尾定位)、binary(二进制),支持|组合。
  • 4 步流程:打开→检查(is_open())→读写→关闭(close()),关键在 "检查" 和 "关闭"。
  • 4 个状态函数:eof()(文件尾)、fail()(可恢复错)、bad()(严重错)、good()(无错)。
  • 补充:appvsate、文本 vs 二进制、getline()>>混用、二进制字节对齐、string禁忌。

一、文件流类

类名 功能 默认模式 核心方法 易错
ifstream 仅读文件 ios::in >>getline() 打开不存在的文件会失败(ofstream会自动创建)
ofstream 仅写文件 ios::out(含trunc <<put() 默认清空文件,追加需显式加ios::app
fstream 读写文件 无(需显式指定) 兼具前两者方法 1. 必须加 ios::inios::out 才支持读写;2. 打开不存在的文件不会自动创建

二、打开模式

模式 作用 补充
ios::in 读权限,文件不存在则失败 fstream需显式加,ifstream默认包含
ios::out 写权限,默认截断 ios::in组合时,文件不存在会失败
ios::app 仅尾追加,指针固定 必须搭配ios::outseekp()移动无效
ios::ate 打开后指针到尾,可移动 支持随机读写,区别于app的核心是 "指针可动"
ios::binary 禁用换行转换 读写结构体 / 图片必须显式指定,否则数据失真

三、操作流程

  1. 打开ifstream ifs("a.txt");fs.open("b.txt", ios::in|ios::out);

  2. 检查if (!ifs.is_open()) { /* 处理失败 */ }

    避免路径错误 / 权限不足导致后续崩溃,必写步骤。

  3. 读写

    • 文本模式(解决getline()>>混用问题):

      1. >>读取数据:ifs >> val;(按空白分割,读取后缓冲区残留换行符\n
      2. 关键处理:ifs.ignore(1024, '\n');(清空缓冲区残留的\n,避免后续getline()读空行)
      3. 读整行数据:getline(ifs, str);(保留空格,正常读取整行)
    • 二进制模式(解决字节对齐和string禁忌问题):

      1. 关闭字节对齐:#pragma pack(1)(跨平台必备,强制结构体成员连续存储)
      2. 定义结构体:struct Student { int id; char name[20]; };(禁用string,用固定长度char数组)
      3. 恢复默认对齐:#pragma pack()
      4. 二进制写入:ofs.write(reinterpret_cast<char*>(&s), sizeof(s));(必须强转为char*类型)
  4. 关闭ifs.close();

    刷新缓冲区(防数据丢失)、释放资源,必写步骤。

易错

  • getline()>>混用:>>残留\n导致空行,用ignore(1024, '\n')清空。
  • 二进制字节对齐:不同编译器对齐规则不同,用#pragma pack(1)强制紧凑存储,避免跨平台错位。
  • string禁忌:二进制读写时,string含指针,写入的是地址,读取崩溃,需用char数组。

四、状态判断函数

函数 含义 典型场景 恢复 / 处理
eof() 到达文件尾 读循环结束判断 正常状态,无需处理
fail() 可恢复错误(格式错等) >>读整数遇字母 恢复:clear()(清错误)+ ignore(1024, '\n')(清缓冲区)
bad() 严重错误(文件损坏) 磁盘故障 不可恢复,终止程序
good() 操作无错 读写正常完成 等价于!eof() && !fail() && !bad()

五、补充

1. ios::appios::ate的区别?

  • app:仅尾追加,写指针固定,不可移动,只能写;
  • ate:初始指针在尾,可通过seekg()/seekp()移动,支持随机读写。

2. 文本与二进制文件操作的区别?

  • 文本:>>/<</getline(),自动转换换行符(\n\r\n),人类可读;
  • 二进制:read()/write()+ios::binary,无转换,原始字节流,效率高,需处理字节对齐。

3. 为什么二进制读写结构体要处理字节对齐?

  • 编译器为提高内存访问效率,会自动对齐结构体成员,导致不同编译器下结构体字节数不一致;
  • 跨平台读取时数据错位,用#pragma pack(1)强制紧凑对齐解决。

4. 不调用close()有什么后果?

  • 缓冲区数据未写入磁盘,程序崩溃可能导致数据丢失;
  • 文件资源被占用,其他程序无法访问;
  • 流对象不可复用。

5. fail()bad()的区别?

  • fail():可恢复(格式错、模式错),用clear()+ignore()恢复;
  • bad():严重错误(磁盘损坏、文件被删),不可恢复。
相关推荐
程序员zgh1 天前
Linux系统常用命令集合
linux·运维·服务器·c语言·开发语言·c++
獭.獭.1 天前
C++ -- STL【unordered_set与unordered_map的实现】
开发语言·c++·unordered_map·unordered_set
qq_433554541 天前
C++数位DP
c++·算法·图论
似水এ᭄往昔1 天前
【C++】--AVL树的认识和实现
开发语言·数据结构·c++·算法·stl
程序员zgh1 天前
常用通信协议介绍(CAN、RS232、RS485、IIC、SPI、TCP/IP)
c语言·网络·c++
暗然而日章1 天前
C++基础:Stanford CS106L学习笔记 8 继承
c++·笔记·学习
有点。1 天前
C++ ⼀级 2023 年06 ⽉
开发语言·c++
charlie1145141911 天前
编写INI Parser 测试完整指南 - 从零开始
开发语言·c++·笔记·学习·算法·单元测试·测试
mmz12071 天前
前缀和问题2(c++)
c++·算法
Alpha first1 天前
C++核心知识点梳理:类型兼容、多继承与虚基类
开发语言·c++