news 2026/1/31 3:21:36

C++ 文件操作速查手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 文件操作速查手册

一、核心头文件与基础类

1. 必备头文件

  • <fstream>:所有文件流操作的核心头文件,包含ifstream/ofstream/fstream三类核心文件流类;
  • <iostream>:提供流基类和基础输入输出能力(如cin/cout),文件流类均继承自其基类;
  • <string>:用于处理文件路径字符串、读写的文本内容;
  • <cstdio>:补充文件重命名、删除等高级操作(兼容 C 标准库)。

2. 核心文件流类

  • std::ifstream:只读文件流,专门用于从文件读取数据(文本 / 二进制均可),默认以ios::in模式打开;
  • std::ofstream:只写文件流,专门用于向文件写入数据(文本 / 二进制均可),默认以ios::out | ios::trunc模式打开;
  • std::fstream:读写文件流,支持同时读取和写入文件,默认以ios::in | ios::out模式打开。

二、文件打开模式

文件打开模式用于指定文件的操作规则,可通过|组合多个模式,所有模式均属于std::ios_base::openmode类型:

  1. ios::in
    • 功能:以只读方式打开文件,文件不存在则打开失败;
    • 适用场景:读取配置文件、文本内容等只读操作,是ifstream的默认模式;
    • 常用组合:ios::in | ios::binary(二进制只读模式)。
  2. ios::out
    • 功能:以只写方式打开文件,文件不存在则自动创建,文件存在则清空原有内容;
    • 适用场景:写入新文件、覆盖原有文件内容,是ofstream的默认模式;
    • 常用组合:ios::out | ios::app(追加写模式)。
  3. ios::app
    • 功能:追加写入模式,所有写入内容都会添加到文件末尾,不会清空原有内容;
    • 适用场景:日志文件写入、累计数据记录等需要保留历史内容的场景。
  4. ios::binary
    • 功能:二进制模式打开文件,不处理换行符(Windows 下\r\n/Linux 下\n)等特殊字符,直接读写原始字节;
    • 适用场景:图片、视频、自定义结构体等非文本数据的读写。
  5. ios::trunc
    • 功能:打开文件时清空原有内容,ios::out模式默认包含此属性;
    • 注意:与ios::app冲突,同时指定时app优先级更高。
  6. ios::ate
    • 功能:打开文件后,文件指针直接定位到文件末尾,可通过指针操作移动到其他位置;
    • 典型用法:快速获取文件总大小(定位到末尾后调用tellg())。

三、核心函数说明(签名 + 功能 + 示例)

1. 文件打开与关闭

(1)构造函数直接打开
  • 签名(以ifstream为例):std::ifstream::ifstream(const std::string& path, std::ios_base::openmode mode = ios::in)
  • 功能:创建流对象的同时打开指定路径的文件,一步完成对象初始化和文件打开;
// 只读打开文本配置文件(默认ios::in模式) std::ifstream config_in("config.txt"); // 追加模式打开日志文件(ios::out + ios::app) std::ofstream log_out("app.log", std::ios::out | std::ios::app);
(2)open () 显式打开
  • 签名:void std::ifstream::open(const std::string& path, std::ios_base::openmode mode = ios::in)
  • 功能:为已创建的空流对象绑定并打开指定文件,适用于需要延迟打开文件的场景;
std::fstream data_fs; // 读写+二进制模式打开数据文件 data_fs.open("data.bin", std::ios::in | std::ios::out | std::ios::binary);
(3)is_open () 检查打开状态
  • 签名:bool std::ifstream::is_open() const
  • 功能:判断文件是否成功打开,返回true表示成功,false表示失败(路径错误、权限不足等);
std::ifstream in("test.txt"); if (!in.is_open()) { std::cerr << "文件打开失败:test.txt" << std::endl; return 1; // 异常退出 }
(4)close () 关闭文件
  • 签名:void std::ifstream::close()
  • 功能:关闭已打开的文件,释放系统文件句柄资源;
std::ofstream out("log.txt"); // 写入内容后显式关闭 out.close();

2. 文本文件读写

(1)getline () 逐行读取
  • 签名:std::istream& std::getline(std::istream& is, std::string& str)
  • 功能:从输入流中读取一行文本(直到换行符,不包含换行符)到字符串变量中;
std::ifstream in("config.txt"); std::string line; // 逐行读取直到文件末尾 while (std::getline(in, line)) { std::cout << "读取行:" << line << std::endl; }
(2)>> 运算符 按空白符读取
  • 功能:从文件流中读取数据(单词、数字等),自动跳过空格、换行、制表符等空白符;
std::ifstream in("num.txt"); // 文件内容:10 20 30 40 int num; // 逐个读取整数 while (in >> num) { std::cout << "读取数字:" << num << std::endl; }
(3)get () 单字符读取
  • 签名:std::istream& std::istream::get(char& c)
  • 功能:读取单个字符(包括空白符、换行符)到字符变量中,保留文件原始格式;​​​​​​​
std::ifstream in("test.txt"); char ch; // 逐字符读取并输出 while (in.get(ch)) { std::cout << ch; }
(4)<< 运算符 格式化写入
  • 功能:与std::cout用法完全一致,向文件流写入格式化数据(字符串、数字、浮点数等);​​​​​​​
std::ofstream out("log.txt"); out << "程序启动时间:" << "2026-01-26" << std::endl; out << "用户ID:" << 1001 << " | 分数:" << 95.5 << std::endl;
(5)put () 单字符写入
  • 签名:std::ostream& std::ostream::put(char c)
  • 功能:向文件流写入单个字符,支持链式调用;​​​​​​​
std::ofstream out("char.txt"); // 链式写入字符,最终文件内容:Hello\n out.put('H').put('e').put('l').put('l').put('o').put('\n');

3. 二进制文件读写

(1)read () 二进制读取
  • 签名:std::istream& std::istream::read(char* buffer, std::streamsize count)
  • 功能:从文件流中读取指定字节数的二进制数据到缓冲区;
// 读取4字节整数(二进制模式) std::ifstream in("data.bin", std::ios::in | std::ios::binary); int num; // 强制转换为char*,读取int大小的字节数 in.read(reinterpret_cast<char*>(&num), sizeof(num)); std::cout << "读取的整数:" << num << std::endl;
(2)write () 二进制写入
  • 签名:std::ostream& std::ostream::write(const char* buffer, std::streamsize count)
  • 功能:将缓冲区中的指定字节数的二进制数据写入文件流;
// 写入自定义结构体(二进制模式) struct Student { int id; char name[20]; float score; }; std::ofstream out("stu.bin", std::ios::out | std::ios::binary); Student s = {1001, "张三", 95.5f}; out.write(reinterpret_cast<const char*>(&s), sizeof(s));

4. 文件指针与随机访问

文件流通过「读指针(get)」和「写指针(put)」实现随机访问,读指针操作函数以g结尾,写指针以p结尾:

(1)seekg () 移动读指针
  • 签名 1(绝对位置):std::istream& std::istream::seekg(std::streampos pos)
  • 签名 2(相对位置):std::istream& std::istream::seekg(std::streamoff off, std::ios_base::seekdir dir)
  • 功能:移动读指针到指定位置,dir可选基准位置:
    • ios::beg:从文件开头偏移;
    • ios::cur:从当前指针位置偏移;
    • ios::end:从文件末尾偏移;​​​​​​​
std::ifstream in("test.txt"); in.seekg(0, std::ios::end); // 指针移到文件末尾(用于获取文件大小) in.seekg(10, std::ios::beg); // 指针移到文件开头后第10字节
(2)tellg () 获取读指针位置
  • 签名:std::streampos std::istream::tellg() const
  • 功能:返回当前读指针的位置(字节数,从文件开头算起);​​​​​​​
std::ifstream in("test.txt"); in.seekg(0, std::ios::end); std::streampos file_size = in.tellg(); // 获取文件总字节数 std::cout << "文件大小:" << file_size << " 字节" << std::endl;
(3)seekp () 移动写指针
  • 功能与签名同seekg(),区别是操作写指针,适用于写文件或读写文件场景;​​​​​​​
std::fstream fs("data.bin", std::ios::in | std::ios::out | std::ios::binary); fs.seekp(5); // 写指针移到第5字节位置(绝对位置)
(4)tellp () 获取写指针位置
  • 功能与签名同tellg(),区别是返回写指针的当前位置;​​​​​​​
std::ofstream out("test.txt"); out << "Hello"; std::streampos pos = out.tellp(); // 返回5("Hello"共5字节)

5. 错误处理函数

文件操作需检查流状态,避免操作失败导致程序异常:

(1)eof()
  • 签名:bool std::ios::eof() const
  • 功能:判断是否到达文件末尾(EOF),返回true表示正常读取到末尾;​​​​​​​
std::ifstream in("test.txt"); std::string line; while (std::getline(in, line)) {} if (in.eof()) { std::cout << "文件读取完成(正常到达末尾)" << std::endl; }
(2)fail()
  • 签名:bool std::ios::fail() const
  • 功能:判断是否发生非致命错误(如格式错误:读取整数时读到字母);​​​​​​​
if (in.fail()) { std::cerr << "文件读取格式错误(非致命)" << std::endl; }
(3)bad()
  • 签名:bool std::ios::bad() const
  • 功能:判断是否发生致命错误(如文件损坏、磁盘故障、流被破坏);​​​​​​​
if (in.bad()) { std::cerr << "文件读取致命错误(如文件损坏)" << std::endl; }
(4)clear()
  • 签名:void std::ios::clear(std::ios_base::iostate state = std::ios_base::goodbit)
  • 功能:清除流的错误状态(如eof()true后,需调用clear()才能继续操作);​​​​​​​
in.clear(); // 清除所有错误状态 in.seekg(0); // 重置读指针到文件开头

6. 高级文件操作

(1)文件重命名
  • 函数:std::rename(来自<cstdio>);
  • 功能:修改文件名,成功返回 0,失败返回非 0;​​​​​​​
#include <cstdio> if (std::rename("old.txt", "new.txt") != 0) { std::cerr << "文件重命名失败" << std::endl; }
(2)文件删除
  • 函数:std::remove(来自<cstdio>);
  • 功能:删除指定文件,成功返回 0,失败返回非 0;​​​​​​​
#include <cstdio> if (std::remove("tmp.txt") != 0) { std::cerr << "文件删除失败" << std::endl; }
(3)获取文件大小
  • 实现方式:结合seekg()tellg();​​​​​​​
std::ifstream in("test.bin", std::ios::binary); in.seekg(0, std::ios::end); // 指针移到末尾 int size = in.tellg(); // 获取字节数 in.seekg(0, std::ios::beg); // 移回开头,方便后续操作 std::cout << "文件大小:" << size << " 字节" << std::endl;

四、常用场景完整示例

场景 1:逐行读取文本配置文件

#include <fstream> #include <iostream> #include <string> using namespace std; int main() { // 打开配置文件 ifstream config_in("config.conf"); if (!config_in.is_open()) { cerr << "配置文件打开失败:config.conf" << endl; return 1; } // 逐行读取并输出 string line; cout << "===== 配置文件内容 =====" << endl; while (getline(config_in, line)) { cout << line << endl; } // 检查读取状态 if (config_in.eof()) { cout << "\n配置文件读取完成" << endl; } config_in.close(); return 0; }

场景 2:追加写入日志文件

#include <fstream> #include <iostream> #include <string> using namespace std; int main() { // 追加模式打开日志文件 ofstream log_out("app.log", ios::out | ios::app); if (!log_out) { cerr << "日志文件打开失败" << endl; return 1; } // 写入日志内容 log_out << "【INFO】程序启动成功 | 时间:2026-01-26 15:30:00" << endl; log_out << "【DEBUG】用户ID:1001 | 操作:登录" << endl; log_out.close(); cout << "日志写入完成" << endl; return 0; }

场景 3:二进制读写结构体数据

#include <fstream> #include <iostream> using namespace std; // 自定义数据结构体 struct UserData { int id; char username[16]; double balance; }; int main() { // 1. 写入二进制数据 ofstream out("user_data.bin", ios::out | ios::binary); if (!out) { cerr << "写入文件打开失败" << endl; return 1; } UserData user = {1002, "李四", 5000.50}; out.write(reinterpret_cast<const char*>(&user), sizeof(user)); out.close(); // 2. 读取二进制数据 ifstream in("user_data.bin", ios::in | ios::binary); if (!in) { cerr << "读取文件打开失败" << endl; return 1; } UserData read_user; in.read(reinterpret_cast<char*>(&read_user), sizeof(read_user)); in.close(); // 输出读取结果 cout << "用户ID:" << read_user.id << endl; cout << "用户名:" << read_user.username << endl; cout << "余额:" << read_user.balance << endl; return 0; }

场景 4:批量打开并读取多个文件

#include <fstream> #include <iostream> #include <vector> #include <string> using namespace std; int main() { // 待打开的文件列表 vector<string> file_list = {"file1.txt", "file2.txt", "file3.txt"}; // 存储多个读流对象(使用移动语义,ifstream不可拷贝) vector<ifstream> file_ins; // 批量打开文件 for (const string& path : file_list) { ifstream in(path); if (!in) { cerr << "跳过失败文件:" << path << endl; continue; } file_ins.push_back(move(in)); // 移动语义存入容器 } // 批量读取每个文件 for (int i = 0; i < file_ins.size(); ++i) { cout << "\n===== 读取文件:" << file_list[i] << " =====" << endl; string line; while (getline(file_ins[i], line)) { cout << line << endl; } file_ins[i].close(); } return 0; }

五、关键注意事项

  1. 打开文件后必须检查is_open():路径错误、权限不足、文件不存在等都会导致打开失败,未检查会引发后续操作崩溃;
  2. 流对象不可拷贝:ifstream/ofstream/fstream均禁用拷贝构造和赋值,批量管理时需用std::move实现移动;
  3. 二进制模式必加ios::binary:读写图片、结构体等非文本数据时,不加此模式会导致换行符被篡改,数据错误;
  4. 错误状态需清除:调用eof()/fail()true后,流会进入错误状态,需用clear()清除后才能继续操作;
  5. 及时关闭文件:虽然流对象析构时会自动关闭文件,但显式调用close()能及时释放文件句柄,避免资源泄露;
  6. 路径分隔符:跨平台代码优先使用/(Windows 和 Linux 均支持),避免\(Windows 专属,需转义为\\)。

总结

  1. 文件操作核心是「流对象 + 打开模式 + 读写方法」,选对类(ifstream/ofstream/fstream)和模式是基础;
  2. 文本文件用getline()/<<读写,二进制文件用read()/write()+ios::binary
  3. 随机访问依赖seekg()/tellg()/seekp()/tellp(),错误处理需结合eof()/fail()/clear()
  4. 批量操作多个文件时,用vector存储流对象并配合移动语义,避免拷贝错误。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/30 18:49:37

cv_resnet18_ocr-detection性能调优:输入尺寸与速度平衡实战

cv_resnet18_ocr-detection性能调优&#xff1a;输入尺寸与速度平衡实战 1. 模型背景与核心价值 1.1 为什么需要关注输入尺寸&#xff1f; OCR文字检测不是“越大越好”的简单逻辑。cv_resnet18_ocr-detection 这个模型&#xff0c;名字里就藏着关键线索&#xff1a;它基于 …

作者头像 李华
网站建设 2026/1/30 17:02:20

4步精通SO100机器人仿真开发:从URDF模型解析到环境部署全指南

4步精通SO100机器人仿真开发&#xff1a;从URDF模型解析到环境部署全指南 【免费下载链接】SO-ARM100 Standard Open Arm 100 项目地址: https://gitcode.com/GitHub_Trending/so/SO-ARM100 机器人仿真开发是快速验证机械设计和控制算法的关键环节&#xff0c;而URDF模型…

作者头像 李华
网站建设 2026/1/29 17:06:05

YOLOv9锚框设计:无Anchor机制原理简析

YOLOv9锚框设计&#xff1a;无Anchor机制原理简析 YOLO系列模型从v1到v8&#xff0c;一直依赖Anchor&#xff08;锚框&#xff09;作为目标检测的先验基础——通过预设一组宽高比和尺度的框&#xff0c;在特征图上密集预测偏移量。但YOLOv9彻底打破了这一惯例&#xff1a;它不…

作者头像 李华
网站建设 2026/1/29 23:39:37

SGLang如何减少重复计算?看完你就明白了

SGLang如何减少重复计算&#xff1f;看完你就明白了 在大模型推理服务的实际部署中&#xff0c;你是否遇到过这样的问题&#xff1a;多轮对话时每次都要重新计算前面几轮的提示词&#xff08;prompt&#xff09;&#xff1f;长上下文场景下KV缓存反复加载、显存占用飙升、首To…

作者头像 李华
网站建设 2026/1/30 4:42:09

Qwen-Image-2512-ComfyUI镜像维护:版本升级与回滚操作指南

Qwen-Image-2512-ComfyUI镜像维护&#xff1a;版本升级与回滚操作指南 1. 为什么需要关注镜像版本维护 你刚用Qwen-Image-2512-ComfyUI生成了一张惊艳的电商主图&#xff0c;正准备批量部署到团队工作流中&#xff0c;突然发现新发布的模型补丁修复了关键的构图偏移问题——但…

作者头像 李华
网站建设 2026/1/30 2:49:45

离线语音识别:无需联网的20+语言实时转写方案

离线语音识别&#xff1a;无需联网的20语言实时转写方案 【免费下载链接】vosk-api vosk-api: Vosk是一个开源的离线语音识别工具包&#xff0c;支持20多种语言和方言的语音识别&#xff0c;适用于各种编程语言&#xff0c;可以用于创建字幕、转录讲座和访谈等。 项目地址: h…

作者头像 李华