c++ std库中的文件操作学习笔记

1. 概述

C++标准库提供了 头文件中的几个类来进行文件操作,这些类封装了底层的文件操作,提供了面向对象和类型安全的接口,使得文件读写更加便捷和高效。主要的文件流类包括:

std::ifstream:用于从文件中读取数据。

std::ofstream:用于向文件中写入数据。

std::fstream:用于同时读取和写入文件。

这些文件流类(std::ifstreamstd::ofstreamstd::fstream)继承自 std::istreamstd::ostreamstd::iostream,这些类本身继承自 std::ios,从而提供了丰富的成员函数和操作符来处理文件I/O。

2. 文件流类详解

2.1 std::ifstream:输入文件流

std::ifstream 用于从文件中读取数据。它继承自 std::istream,具备所有输入流的功能,同时添加了文件特有的操作。


#include <fstream>
#include <iostream>
#include <string>int main() {// 创建并打开输入文件流std::ifstream infile("input.txt"); // "input.txt" 是要读取的文件名// 检查文件是否成功打开if (!infile) {std::cerr << "无法打开文件 input.txt" << std::endl;return 1;}// 读取并输出文件内容std::string line;while (std::getline(infile, line)) {std::cout << line << std::endl;}// 关闭文件流(可选,因为析构函数会自动关闭)infile.close();return 0;
}

要点:

  • 构造函数可以在创建对象时指定文件名和打开模式。

  • 检查文件是否成功打开,以避免后续操作错误。

  • 使用 std::getline 逐行读取文件内容。

2.2 std::ofstream:输出文件流

std::ofstream 用于向文件中写入数据。它继承自 std::ostream,具备所有输出流的功能,同时添加了文件特有的操作。


#include <fstream>
#include <iostream>
#include <string>int main() {// 创建并打开输出文件流std::ofstream outfile("output.txt"); // "output.txt" 是要写入的文件名// 检查文件是否成功打开if (!outfile) {std::cerr << "无法打开文件 output.txt" << std::endl;return 1;}// 写入数据到文件outfile << "Hello, World!" << std::endl;outfile << "这是第二行文本。" << std::endl;// 关闭文件流(可选,因为析构函数会自动关闭)outfile.close();return 0;
}

要点:

  • 默认情况下,std::ofstream 以写入模式打开文件。如果文件不存在,会创建新文件;如果文件存在,会截断文件内容。

  • 使用<<操作符向文件中插入数据。

2.3 std::fstream:文件流(读写)

std::fstream 用于同时读取和写入文件。它继承自std::iostream,结合了 std::istream 和 std::ostream 的功能


#include <fstream>
#include <iostream>
#include <string>int main() {// 创建并打开文件流,设置为读写模式std::fstream file("file.txt", std::ios::in | std::ios::out | std::ios::app);// 检查文件是否成功打开if (!file) {std::cerr << "无法打开文件 file.txt" << std::endl;return 1;}// 写入数据到文件file << "追加一行内容。" << std::endl;// 移动读指针到文件开头file.seekg(0, std::ios::beg);// 读取并输出文件内容std::string line;while (std::getline(file, line)) {std::cout << line << std::endl;}// 关闭文件流file.close();return 0;
}

要点:

  • 通过构造函数的第二个参数指定文件打开模式,可以组合多个模式。

  • 适用于需要同时进行读取和写入操作的场景。

3. 打开和关闭文件

文件流类提供了多种方式来打开和关闭文件。

可以在创建文件流对象时,通过构造函数直接指定文件名和打开模式。


std::ifstream infile("input.txt"); // 以默认模式(即只读方式)打开 input.txt
std::ofstream outfile("output.txt", std::ios::out | std::ios::trunc); // 以写入和截断模式打开 output.txt

如果在创建对象时没有指定文件名,可以使用 open() 成员函数在后续打开文件。


#include <fstream>
#include <iostream>int main() {std::ifstream infile; // 创建输入文件流对象infile.open("input.txt"); // 打开文件if (!infile.is_open()) {std::cerr << "无法打开文件 input.txt" << std::endl;return 1;}// 进行读取操作...infile.close(); // 关闭文件return 0;
}

使用 close() 成员函数可以显式关闭文件流。尽管在对象销毁时,析构函数会自动关闭文件,但在需要提前释放资源时,显式调用 close() 是必要的。


infile.close();
outfile.close();

4. 文件打开模式

文件打开模式通过 std::ios::openmode 枚举类型指定,可以组合使用多个模式。

常用的打开模式:

- std::ios::in:以读取模式打开文件。

  • std::ios::out:以写入模式打开文件。

  • std::ios::app:以追加模式打开文件,写入操作将添加到文件末尾。

  • std::ios::ate:打开文件后,将文件指针定位到文件末尾。

  • std::ios::trunc:如果文件已存在,则截断文件长度为0(默认与 std::ofstream 相关)。

  • std::ios::binary:以二进制模式打开文件。


// 以读写模式打开文件,不截断现有内容
std::fstream file("data.txt", std::ios::in | std::ios::out);// 以二进制模式写入数据, 截断现有文件内容std::ofstream binaryOut("data.bin", std::ios::out | std::ios::binary | std::ios::trunc);

说明:

  • 组合使用:通过按位或操作符 | 组合多个打开模式,如 std::ios::in | std::ios::out 表示同时具备读取和写入权限。

  • 二进制模式:对于非文本文件(如图片、音频等),应使用 std::ios::binary 模式,以防止数据在读取或写入过程中被转换。

5. 读取文件

5.1 使用 >> 操作符读取单词

>> 操作符用于从文件中提取数据,自动跳过空白字符(如空格、换行符、制表符)。

假设 words.txt 文件内容如下:
在这里插入图片描述


#include <fstream>
#include <iostream>
#include <string>int main() {std::ifstream infile("words.txt");if (!infile) {std::cerr << "无法打开文件 words.txt" << std::endl;return 1;}std::string word;while (infile >> word) { // 逐词读取std::cout << "读取到的单词: " << word << std::endl;}infile.close();return 0;
}

输出如下:
在这里插入图片描述
说明:

  • 适用于逐词读取数据,适合处理由空白字符分隔的数据。

  • 无法读取包含空格的完整句子或短语。

5.2 使用 std::getline 逐行读取

std::getline 函数用于从文件中逐行读取数据,适用于处理文本文件中的行数据。

假设 lines.txt 文件内容如下:
在这里插入图片描述


#include <fstream>
#include <iostream>
#include <string>int main() {std::ifstream infile("lines.txt");if (!infile) {std::cerr << "无法打开文件 lines.txt" << std::endl;return 1;}std::string line;while (std::getline(infile, line)) { // 逐行读取std::cout << "读取到的行: " << line << std::endl;}infile.close();return 0;
}

输出如下:
在这里插入图片描述
说明:

  • 适用于逐行处理文件内容,保留每行的完整信息。

  • 可以处理包含空格和其他特殊字符的行。

5.3 读取整个文件内容

有时需要一次性读取整个文件内容,尤其适用于小文件或需要对整个文件内容进行处理的场景。
假设 content.txt 文件内容如下:
在这里插入图片描述


#include <fstream>
#include <iostream>
#include <string>int main() {std::ifstream infile("content.txt");if (!infile) {std::cerr << "无法打开文件 content.txt" << std::endl;return 1;}// 使用迭代器读取整个文件内容到字符串std::string content((std::istreambuf_iterator<char>(infile)),std::istreambuf_iterator<char>());std::cout << "文件内容:\n" << content << std::endl;infile.close();return 0;
}

输出如下:
在这里插入图片描述
说明:

使用 std::istreambuf_iterator 迭代器可以高效地读取整个文件内容。

适用于小至中等大小的文件,对于非常大的文件,可能需要分块读取以避免内存问题。

对此行代码的理解:

std::string content((std::istreambuf_iterator<char>(infile)),std::istreambuf_iterator<char>());
  • 这行代码使用了 std::istreambuf_iterator 来从输入文件流 infile 读取内容并构建一个 std::string 对象。具体理解如下:

  • std::istreambuf_iterator(infile):创建一个输入迭代器,从 infile 的缓冲区读取字符。

  • std::istreambuf_iterator():这是一个空的迭代器,用于表示输入结束。
    构造 std::string:通过传入两个迭代器,构造函数会从 infile 中读取所有字符,直到遇到结束迭代器。

  • 最终,这行代码的作用是将整个文件的内容读入到 content 字符串中。这样,你就可以方便地对文件内容进行操作。

5.4 读取二进制数据

对于非文本文件(如图片、音频、视频等),需要以二进制模式读取数据,以防止数据在读取过程中被转换或丢失。
假设需要读取一个图片文件 image.jpg 并输出其大小。
在这里插入图片描述


#include <fstream>
#include <iostream>
#include <vector>int main() {// 以二进制模式打开文件std::ifstream infile("image.jpg", std::ios::binary);if (!infile) {std::cerr << "无法打开文件 image.jpg" << std::endl;return 1;}// 移动读指针到文件末尾以获取文件大小//这行代码将文件指针移动到文件的末尾。seekg 函数用于设置输入流的位置,0 是偏移量infile.seekg(0, std::ios::end);//tellg 函数返回当前文件指针的位置(即文件的长度)std::streamsize size = infile.tellg();//这行代码将文件指针重置回文件的开头infile.seekg(0, std::ios::beg);// 读取文件内容到缓冲区std::vector<char> buffer(size);if (infile.read(buffer.data(), size)) {std::cout << "成功读取 " << size << " 字节。" << std::endl;} else {std::cerr << "读取文件失败!" << std::endl;}infile.close();return 0;
}

输出如下:
在这里插入图片描述
说明:

  • 使用 std::ios::binary 模式打开文件,确保数据按原样读取。

  • 通过 seekg tellg获取文件大小,预分配缓冲区。

  • 使用read函数读取二进制数据到缓冲区。

6. 写入文件

6.1 使用 << 操作符写入数据

<< 操作符用于向文件中插入数据,类似于向标准输出流 std::cout 中插入数据。

将用户信息写入文件 users.txt。


#include <fstream>
#include <iostream>
#include <string>int main() {std::ofstream outfile("users.txt");if (!outfile) {std::cerr << "无法打开文件 users.txt" << std::endl;return 1;}// 写入用户信息outfile << "用户名: Alice\n年龄: 30\n" << std::endl;outfile << "用户名: Bob\n年龄: 25\n" << std::endl;outfile << "用户名: Charlie\n年龄: 35\n" << std::endl;outfile.close();std::cout << "用户信息已写入 users.txt" << std::endl;return 0;
}

输出如下:
在这里插入图片描述
文件即自动创建于当前工程根目录下

说明:

  • 使用 << 操作符可以方便地将各种数据类型写入文件。

  • std::endl 用于插入换行符并刷新缓冲区。

6.2 使用 std::ofstream::write 写入二进制数据

对于需要写入二进制数据的场景,使用 write() 成员函数更为合适。

将一个字符数组写入二进制文件 output.bin。


#include <fstream>
#include <iostream>
#include <vector>int main() {std::ofstream outfile("output.bin", std::ios::binary | std::ios::trunc);if (!outfile) {std::cerr << "无法打开文件 output.bin" << std::endl;return 1;}// 准备二进制数据std::vector<char> data = {'H', 'e', 'l', 'l', 'o', '\0'};// 写入二进制数据到文件outfile.write(data.data(), data.size());if (!outfile) {std::cerr << "写入文件失败!" << std::endl;} else {std::cout << "成功写入 " << data.size() << " 字节到 output.bin" << std::endl;}outfile.close();return 0;
}

data.data():获取 data 字符串的指针,指向字符串的首字符。这是写入的起始地址。
data.size():返回字符串 data 的长度,表示要写入的字节数。
outfile.write(data.data(), data.size());:调用 write 函数,将从 data 指针开始的 data.size() 字节写入 outfile 中。

输出如下:
在这里插入图片描述
说明:

  • 使用 write() 可以指定要写入的数据地址和字节数,适用于二进制数据。

  • 确保文件以二进制模式打开,防止数据被意外转换。

7. 一个实际使用的示例

读取mysql中conf文件的配置:

bool ConnectionPool::loadConfigFile()
{//setenv("MYSQL_CONF_PATH","/home/kyros1ee/QtEnviroment/WeChat-main/chatserver/conf/mysql.conf",1);// 设置环境变量或绝对路径const char* configPath = getenv("MYSQL_CONF");	//if (!configPath){LOG_ERROR << " mysql.conf MYSQL_CONF_PATH not set!";return false;}ifstream file(configPath);if (!file.is_open()){LOG_ERROR << "mysql.conf 文件不存在!";return false;}string line;while (getline(file, line)){// 忽略空行和注释行if (line.empty() || line.find('=') == string::npos)continue;if (line.back() == '\r') {line.pop_back();}istringstream iss(line);string key, value;if (getline(iss, key, '=') && getline(iss, value)){// 去除可能存在的前后空白key = trim(key);value = trim(value);if (key == "ip") _ip = value;else if (key == "port") _port = stoi(value);else if (key == "username") _username = value;else if (key == "password") _password = value;else if (key == "dbname") _dbname = value;else if (key == "initSize") _initSize = stoi(value);else if (key == "maxSize") _maxSize = stoi(value);else if (key == "maxIdleTime") _maxIdleTime = stoi(value);else if (key == "connectionTime") _connectionTimeout = stoi(value);}}return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/80230.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】SQL注入

如果文章不足还请各位师傅批评指正&#xff01; 想象一下&#xff0c;你经营着一家咖啡店&#xff0c;顾客可以通过店内的点单系统下单。这个系统会根据顾客的输入&#xff0c;向后厨发送指令&#xff0c;比如“为顾客A准备一杯拿铁”。 然而&#xff0c;如果有个不怀好意的顾客…

解决Mawell1.29.2启动SQLException: You have an error in your SQL syntax问题

问题背景 此前在openEuler24.03 LTS环境下的Hive使用了MySQL8.4.2&#xff0c;在此环境下再安装并启动Maxwell1.29.2时出现如下问题 [ERROR] Maxwell: SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version f…

Oracle APEX IR报表列宽调整

目录 1. 问题&#xff1a;如何调整Oracle APEX IR报表列宽 2. 解决办法 1. 问题&#xff1a;如何调整Oracle APEX IR报表列宽 1-1. 防止因标题长而数据短&#xff0c;导致标题行的文字都立起来了&#xff0c;不好看。 1-2. 防止因数据太长而且中间还没有空格&#xff0c;把列…

pytorch 14.3 Batch Normalization综合调参实践

文章目录 一、Batch Normalization与Batch_size综合调参二、复杂模型上的Batch_normalization表现1、BN对复杂模型&#xff08;sigmoid&#xff09;的影响2、模型复杂度对模型效果的影响3、BN对复杂模型&#xff08;tanh&#xff09;的影响 三、包含BN层的神经网络的学习率优化…

Model.eval() 与 torch.no_grad() PyTorch 中的区别与应用

Model.eval() 与 torch.no_grad(): PyTorch 中的区别与应用 在 PyTorch 深度学习框架中&#xff0c;model.eval() 和 torch.no_grad() 是两个在模型推理&#xff08;inference&#xff09;阶段经常用到的函数&#xff0c;它们各自有着独特的功能和应用场景。本文将详细解析这两…

Swagger go中文版本手册

Swaggo(github.com/swaggo/swag)的注解语法是基于 OpenAPI 2.0 (以前称为 Swagger 2.0) 规范的,并添加了一些自己的约定。 主要官方文档: swaggo/swag GitHub 仓库: 这是最权威的来源。 链接: https://github.com/swaggo/swag重点关注: README.md: 包含了基本的安装、使用…

物联网设备远程管理:基于代理IP的安全固件更新通道方案

在物联网设备远程管理中&#xff0c;固件更新的安全性直接关系到设备功能稳定性和系统抗攻击能力。结合代理IP技术与安全协议设计&#xff0c;可构建安全、高效的固件更新通道。 一、代理IP在固件更新中的核心作用 网络层隐匿与路由优化 隐藏更新源服务器&#xff1a;通过代理I…

【C++重载操作符与转换】句柄类与继承

目录 一、句柄类的基本概念 1.1 什么是句柄类 1.2 句柄类的设计动机 1.3 句柄类的基本结构 二、句柄类的实现方式 2.1 基于指针的句柄类 2.2 值语义的句柄类 2.3 引用计数的句柄类 三、句柄类与继承的结合应用 3.1 实现多态容器 3.2 实现插件系统 3.3 实现状态模式…

谷歌曾经的开放重定向漏洞(如今已经修复) -- noogle DefCamp 2024

题目描述: 上周&#xff0c;我决定创建自己的搜索引擎。这有点难&#xff0c;所以我背上了另一个。我也在8000端口上尝试了一些东西。 未发现题目任何交互,但是存在一个加密js const _0x43a57f _0x22f9; (function(_0x3d7d57, _0x426e05) {const _0x16c3fa _0x22f9, _0x3187…

【C#】ToArray的使用

在 C# 中&#xff0c;ToArray 方法通常用于将实现了 IEnumerable<T> 接口的集合&#xff08;如 List<T>&#xff09;转换为数组。这个方法是 LINQ 提供的一个扩展方法&#xff0c;位于 System.Linq 命名空间中。因此&#xff0c;在使用 ToArray 方法之前&#xff0…

资产管理平台—chemex

1、简介 Chemex CMDB&#xff08;Configuration Management Database&#xff09;是一个基于现代微服务架构的资产管理与自动化平台&#xff0c;专为 IT 基础设施与业务资产管理而设计。其核心目标是解决大规模系统运维中资产信息混乱、配置分散、数据不一致等问题&#xff0c…

【AI】mcp server是什么玩意儿

文章目录 背景mcp server的必要性mcp server的基本概念mcp server的架构与核心组件总结 背景 劈里啪啦的整了一堆概念&#xff0c;对mcp server还是只停留在知道个词的地步。 虽然目前大模型的对话生成能力很强&#xff0c;但是大模型&#xff08;如deepseek&#xff09;并不能…

c# 数据结构 树篇 入门树与二叉树的一切

事先声明,本文不适合对数据结构完全不懂的小白 请至少学会链表再阅读 c# 数据结构 链表篇 有关单链表的一切_c# 链表-CSDN博客 数据结构理论先导:《数据结构&#xff08;C 语言描述&#xff09;》也许是全站最良心最通俗易懂最好看的数据结构课&#xff08;最迟每周五更新~~&am…

《Cookie Cutter》中2000多张精灵表与10000个2D光源的管理之道

一个小团队如何在多个平台上以优秀的效果展示手绘动画&#xff1f;Subcult Joint 工作室给出了答案。他们用六年时间开发出了游戏《Cookie Cutter》。游戏中使用了数千个使用传统动画技术制作的高分辨率资产&#xff0c;而且这些资产都在 Unity 中进行了优化。由于工作室需要在…

什么是实景VR?实景VR应用场景

实景VR&#xff0c;即基于真实场景的虚拟现实技术&#xff0c;是利用计算机技术生成三维环境&#xff0c;以模拟并再现真实世界场景的技术。 用户通过佩戴VR设备&#xff08;如VR头盔、手柄等&#xff09;或通过电脑设备&#xff0c;可以沉浸在一个高度仿真的虚拟环境中&#…

内核性能测试(60s不丢包性能)

以xGAP-200-SE7K-L&#xff08;双口10G&#xff09;在飞腾D2000上为例&#xff08;单通道最高性能约2.8Gbps) 单口测试 0口&#xff1a; tcp&#xff1a; taskset -c 4 iperf -c 1.1.1.1 -i 1 -t 60 -p 60001 taskset -c 4 iperf -s -i 1 -p 60001 udp&#xff1a; taskse…

58. 区间和

题目链接&#xff1a; 58. 区间和 题目描述&#xff1a; 给定一个整数数组 Array&#xff0c;请计算该数组在每个指定区间内元素的总和。 输入描述 第一行输入为整数数组 Array 的长度 n&#xff0c;接下来 n 行&#xff0c;每行一个整数&#xff0c;表示数组的元素。随后…

C#进阶(2)stack(栈)

前言 我们前面介绍了ArrayList,今天就介绍另一种数据结构——栈。 这是栈的基本形式,博主简单画了一下,你看个意思就行,很明显,这种数据有一种特征:先进后出。因为先进来的数据会在下面,下面是密闭的,所以只能取后面进来的。 C#为我们封好了这种数据结构,我们不用担…

汽车工厂数字孪生实时监控技术从数据采集到三维驱动实现

在工业智能制造推动下&#xff0c;数字孪生技术正成为制造业数字化转型的核心驱动力。今天详细介绍数字孪生实时监控技术在汽车工厂中的应用&#xff0c;重点解析从数据采集到三维驱动实现的全流程技术架构&#xff0c;并展示其在提升生产效率、降低成本和优化决策方面的显著价…

git|gitee仓库同步到github

参考&#xff1a;一次提交更新两个仓库&#xff0c;Get 更优雅的 GitHub/Gitee 仓库镜像同步 文章目录 进入需要使用镜像功能的仓库&#xff0c;进入「管理」找到「仓库镜像管理」选项&#xff0c;点击「添加镜像」按钮绑定github绑定成功后再次点击添加镜像如何申请 GitHub 私…