[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():严重错误(磁盘损坏、文件被删),不可恢复。
相关推荐
君生我老4 小时前
C++自写list类
c++
阿猿收手吧!4 小时前
【C++】异步编程:std::async终极指南
开发语言·c++
REDcker4 小时前
gRPC开发者快速入门
服务器·c++·后端·grpc
doupoa4 小时前
内存指针是什么?为什么指针还要有偏移量?
android·c++
冉佳驹5 小时前
C++ ——— 异常处理的核心机制和智能指针管理
c++·异常捕获·异常继承体与多态·重载抛异常·raii思想·智能指针shared_ptr·weak_ptr指针
C++ 老炮儿的技术栈5 小时前
Qt 编写 TcpClient 程序 详细步骤
c语言·开发语言·数据库·c++·qt·算法
yuuki2332335 小时前
【C++】继承
开发语言·c++·windows
梵刹古音5 小时前
【C++】 析构函数
开发语言·c++
wangjialelele5 小时前
Linux下的IO操作以及ext系列文件系统
linux·运维·服务器·c语言·c++·个人开发
打工哪有不疯的6 小时前
使用 MSYS2 为 Qt (MinGW 32/64位) 完美配置 OpenSSL
c++·qt