【C++】文件处理(IO流)

文章目录

  • C++ IO流
    • 1. C语言IO
    • 2. C++IO
      • 2.1 C++标准IO流
      • 2.2 C++文件IO流
      • 2.3 C++ IO 文件常用函数总结表
      • 2.4 C++ stringstream


C++ IO流

回顾一下,C语言中IO输入输出的

1. C语言IO

C语言中常用的输入输出函数有如下几种:前者是格式化标准输入输出,后者是格式化文件输入输出,最后是格式化字符串输入输出。

函数名内容
scanf从标准输入流(键盘)读取格式化的数据
fscanf从所有输入流读取读取格式化数据
sscanf从字符串中读取格式化的数据
printf将格式化的数据输出到标准输出流(屏幕)上
fprintf将格式化数据输出到所有输出流上
sprintf将格式化的数据输出到字符串中

文件的输入输出需要以下几个函数:

函数名功能
fopen打开文件流
fclose关闭文件流
fscanf从所有输入流读取读取格式化数据
fprintf将格式化数据输出到所有输出流上
fread二进制输入
fwrite二进制输出
//文件开关
FILE* fopen   (const char* filename, const char* mode);
int   fclose  (FILE* stream);
//格式化读写
int fprintf (FILE* stream, const char* format [, argument ]...);
int fscanf  (FILE* stream, const char* format [, argument ]...);
//二进制读写
size_t fwrite  (const void* buffer, size_t size, size_t count, FILE* stream);
size_t fread   (      void* buffer, size_t size, size_t count, FILE* stream);

使用方式如下:

struct ServerInfo 
{char _ip[32];int _port;friend ostream& operator<<(ostream& os, ServerInfo& info);friend ostream& operator>>(ostream& os, ServerInfo& info);
};
//测试C语言二进制读写
void TestC_Write_Bin() {ServerInfo info = { "192.168.1.1",80 };FILE* fout = fopen("info.bin", "wb");//assert();fwrite(&info, sizeof(ServerInfo), 1, fout);fclose(fout);
}
void TestC_Read_Bin() {ServerInfo info;FILE* fin = fopen("info.bin", "rb");fread(&info, sizeof(ServerInfo), 1, fin);printf("%s:%d", info._ip, info._port);fclose(fin);
}
//测试C语言字符读写
void TestC_Write_Text() {ServerInfo info = { "192.168.1.1",80 };FILE* fout = fopen("info.txt", "w");fprintf(fout, "%s %d", info._ip, info._port);fclose(fout);
}
void TestC_Read_Text() {ServerInfo info;FILE* fin = fopen("info.txt", "r");fscanf(fin, "%s %d", &info._ip, &info._port);printf("%s:%d", info._ip, info._port);
}

 

2. C++IO

C++ 标准库提供了4个全局流对象cincoutcerrclog。cout、cerr、clog 是 ostream 类的三个不同的对象。使用 cout 进行标准输出,使用 cin 进行标准输入。同时 C++ 标准库还提供了 cerr 用来进行标准错误的输出,以及 clog 进行日志的输出。

以下是常用的标准输入输出对象:

  • cin:标准输入流对象。
  • cout:标准输出流对象。
  • cerr:标准错误输出流对象,通常用于输出错误信息。
  • clog:标准日志流对象,用于输出日志信息。

2.1 C++标准IO流

cout,cinostream,istream类的对象,operator<<,operator>>分别是两个对象的操作符重载成员函数。

C++输出输入可直接使用cout>>cin>>,因为其重载了所有内置类型,对于自定义类型需要自行重载操作符>><<

cin >> a >> b;

operator<<operator>>的返回值也是ostream&istream&,因此支持连续输入输出,又是一次函数调用。

cout/cin 取代 printf/scanf 的真正原因是 cout/cin 支持自定义类型,符合面向对象的思想。

当需要循环读入数据时,可以采用如下的方式:

string str;
while (cin >> str) {;
}

从文档中可以看到,operator>>的返回值是istream类型,这个对象类型是如何作真假判断的呢?

原因是istream类的对象支持一个操作符的重载函数叫operator bool,C++98中叫operator void*,C++11中叫operator bool

这是个特殊的运算符重载函数,该函数不允许限定返回类型,当类型被当作条件判断时,自动调用并将返回值强转为内置的标识,该标识如果为真就继续,如果为假就停止读取。

2.2 C++文件IO流

采用面向对象的思想,C++中文件指针被文件输入输出流对象ofstreamifstream代替。

fopen的调用方式类似,创建输入输出流对象,调用其构造函数传入文件地址以及打开模式。fclose被析构函数代替,且析构函数可以自动调用。
 

主要的两个IO类

对象构造函数解释
ofstream (const char fileName, ios_base::openmode mode=ios_base::out)*创建输出流对象,并指定文件地址和打开模式
ifstream (const char fileName, ios_base::openmode mode=ios_base::in)*创建输入流对象,并指定文件地址

ofstream-写文件:

//1. 按字符写入文件内容
void writeCharByChar(const std::string& fileName, const std::string& content) {std::ofstream ofs(fileName);if (!ofs) {std::cerr << "无法打开文件进行写入!" << std::endl;return;}for (char c : content) {ofs.put(c);}ofs.close();
}//2. 使用 put() 方法写入文件内容
void writeUsingPut(const std::string& fileName, const std::string& content) {std::ofstream ofs(fileName);if (!ofs) {std::cerr << "无法打开文件进行写入!" << std::endl;return;}for (char c : content) {ofs.put(c);}ofs.close();
}//3. 按行写入文件内容
void writeLineByLine(const std::string& fileName, const std::string& content) {std::ofstream ofs(fileName);if (!ofs) {std::cerr << "无法打开文件进行写入!" << std::endl;return;}ofs << content << std::endl;ofs.close();
}//4. 使用 write() 方法写入文件内容
void writeUsingWrite(const std::string& fileName, const std::string& content) {std::ofstream ofs(fileName, std::ios::binary);if (!ofs) {std::cerr << "无法打开文件进行写入!" << std::endl;return;}ofs.write(content.c_str(), content.size());ofs.close();
}

 

当然,请看下面的表格,它列出了C++中常用的文件打开模式及其解释:

模式解释
ios::in输入模式,用于读取文件。
ios::out输出模式,用于写入文件。
ios::binary二进制模式,用于以二进制方式读写文件。
ios::ate在文件末尾打开文件,初始位置为文件末尾。
ios::app追加模式,用于在文件末尾追加内容而不覆盖已有内容。
ios::trunc如果文件已存在,则清空文件内容。
ios::in | ios::binary同时指定输入模式和二进制模式,用于以二进制方式读取文件。
ios::out | ios::binary同时指定输出模式和二进制模式,用于以二进制方式写入文件。

常用的有如上几种,该变量的值以二进制位中的不同位为1来标识,也就是说使用异或|就可以组合起来用。

ifstream-读取文件

// 1.按字符读取文件内容
void readCharByChar(const std::string& fileName) {std::ifstream ifs(fileName);if (!ifs) {std::cerr << "无法打开文件进行读取!" << std::endl;return;}char c;// 逐个字符读取文件内容并输出while (ifs.get(c)) {std::cout << c;}ifs.close();
}// 2.使用 get() 方法读取文件内容
void readUsingGet(const std::string& fileName) {std::ifstream ifs(fileName);if (!ifs) {std::cerr << "无法打开文件进行读取!" << std::endl;return;}char buffer[128];// 逐块读取文件内容并输出,每次读取最多128个字符while (ifs.get(buffer, sizeof(buffer))) {std::cout << buffer;}ifs.close();
}// 3.按行读取文件内容
void readLineByLine(const std::string& fileName) {std::ifstream ifs(fileName);if (!ifs) {std::cerr << "无法打开文件进行读取!" << std::endl;return;}std::string line;// 逐行读取文件内容并输出while (std::getline(ifs, line)) {std::cout << line << std::endl;}ifs.close();
}// 4.使用 read() 方法读取文件内容
void readUsingRead(const std::string& fileName) {std::ifstream ifs(fileName, std::ios::binary);if (!ifs) {std::cerr << "无法打开文件进行读取!" << std::endl;return;}// 移动到文件末尾ifs.seekg(0, std::ios::end);// 获取文件大小std::streampos fileSize = ifs.tellg();// 移动回文件开头ifs.seekg(0, std::ios::beg);char buffer[128];// 逐块读取文件内容并输出,每次读取最多128个字符while (ifs.read(buffer, sizeof(buffer))) {std::cout.write(buffer, ifs.gcount());}// 处理剩余的字符ifs.read(buffer, sizeof(buffer));std::cout.write(buffer, ifs.gcount());ifs.close();
}

 

函数:

函数解释
istream& read(char s, streamsize n);*read接口是输入流istream对象的成员函数,参数是变量和大小。
ostream& write(const char s , streamsize n);*write接口是输出流ostream对象的成员函数,参数是写入变量和写入大小。

示例

使用一个ConfigManage类来演示几种文件读写的方式。

struct ServerInfo 
{char _ip[32];int _port;friend ostream& operator<<(ostream& os, ServerInfo& info);friend ostream& operator>>(ostream& os, ServerInfo& info);
};
class ConfigManage {
public:ConfigManage(const char* fileName):_fileName(fileName){}//二进制写入void WriteBin(ServerInfo& info){ofstream ofs(_fileName.c_str(), ios_base::out | ios_base::binary); //创建输出流对象ofs.write((const char*)&info, sizeof(ServerInfo)); //调用write接口}//二进制读取void ReadBin(ServerInfo& info){ifstream ifs(_fileName.c_str(), ios_base::in | ios_base::binary);ifs.read((char*)&info, sizeof(ServerInfo));cout << info << endl;}
private:string _fileName;
};

读写文件更常用的方式是以文本形式读写,因此就可以省略打开模式参数。

ifstream,ofstream文件输入输出类中还继承了iostream的流插入<<流提取>>操作符,也就是对象ofsifs也可以使用<<>>操作符。

struct ServerInfo {friend ostream& operator<<(ostream& os, ServerInfo& info);friend ostream& operator>>(ostream& os, ServerInfo& info);char _ip[32];int _port;
};
ostream& operator<<(ostream& os, ServerInfo& info) {os << info._ip << " " << info._port;return os;
}
istream& operator>>(istream& is, ServerInfo& info) {is >> info._ip >> info._port;return is;
}
//文本写入
void WriteText(ServerInfo& info)
{ofstream ofs(_fileName.c_str());//writeofs.write((const char*)&info, sizeof(ServerInfo));//1.ofs << info._ip << info._port; //对象未重载<<//2.ofs << info; //对象已重载>>
}
//文本读取
void ReadText(ServerInfo& info)
{ifstream ifs(_fileName.c_str());//readifs.read((char*)&info, sizeof(ServerInfo));//1.ofs << info._ip << info._port; //对象未重载<<//2.ifs >> info; //对象已重载>>cout << info << endl;
}

具体调用方式则是如下:

void TestCPP_Write_Bin() {ServerInfo info = { "192.168.1.1",80 };ConfigManage con("config.bin");con.WriteBin(info);
}
void TestCPP_Read_Bin() {ServerInfo info;ConfigManage con("config.bin");con.ReadBin(info);
}
void TestCPP_Write_Text() {ServerInfo info = { "192.168.1.1",80 };ConfigManage con("config.bin");con.WriteText(info);
}
void TestCPP_Read_Text() {ServerInfo info;ConfigManage con("config.bin");con.ReadText(info);
}

文件的输入输出流对象调用构造函数时也可能会失败,C++采取面向对象抛异常的形式。

2.3 C++ IO 文件常用函数总结表

函数及操作符说明
文件位置操作
ifs.seekg(pos)设置输入位置指针到指定位置。
ofs.seekp(pos)设置输出位置指针到指定位置。
ifs.tellg()返回输入位置指针的当前位置。
ofs.tellp()返回输出位置指针的当前位置。
按字符读取和写入
ifs.get(char& ch)从输入流中读取一个字符。
ofs.put(char ch)向输出流中写入一个字符。
按行读取和写入
std::getline(ifs, std::string& str)从输入流中读取一行文本,存储到字符串中。
ofs << str向输出流中写入一个字符串。
读取和写入块数据
ifs.read(char* buffer, streamsize n)从输入流中读取n个字符到缓冲区中。
ofs.write(const char* buffer, streamsize n)将缓冲区中的n个字符写入输出流中。
流状态检查
ifs.eof()判断输入流是否到达文件末尾。
ifs.fail()判断输入流是否发生读取错误。
ifs.good()判断输入流是否处于良好状态。
ifs.clear()清除流的错误状态标志。
字符串流
std::istringstream iss创建字符串输入流。
std::ostringstream oss创建字符串输出流。
iss.str(std::string str)将字符串设置为输入流的内容。
oss.str()获取输出流的字符串内容。
流插入和提取操作符
ifs >> var从输入流中提取数据到变量。
ofs << var将变量的数据插入输出流。

2.4 C++ stringstream

在头文件 下,有三个类:istringstream、ostringstream 和 stringstream,分别用来进行字符串流的输入、输出和输入输出操作。

  • istringstream类用于从字符串中提取数据,类似于从文件或标准输入流中读取数据。它可以将字符串内容转换为各种数据类型。

  • ostringstream类用于将数据写入字符串,类似于将数据写入文件或标准输出流。它可以将各种数据类型转换为字符串。

  • stringstream 类同时支持字符串输入和输出操作。它可以在同一个对象中进行数据的读取和写入。

    在这里插入图片描述

下面的示例代码展示了如何使用 ostringstreamistringstream 对自定义对象进行序列化和反序列化

struct PersonInfo {std::string _name;int _age;friend std::ostream& operator<<(std::ostream& os, const PersonInfo& info) {os << info._name << " " << info._age;return os;}friend std::istream& operator>>(std::istream& is, PersonInfo& info) {is >> info._name >> info._age;return is;}
};int main() {// 序列化PersonInfo info1 = { "zhangsan", 20 };std::ostringstream oss;// 1. 使用对象未重载 << 操作符oss << info1._name << " " << info1._age;// 2. 使用对象已重载 << 操作符oss << " " << info1;std::string str = oss.str();std::cout << "序列化后的字符串: " << str << std::endl;// 反序列化PersonInfo info2;std::istringstream iss(str);iss.str(str);return 0;
}

使用 stringstream类也可以达到同样的效果:

std::stringstream ss;
ss << info1; // 写入对象到字符串流
ss << " serialized"; // 追加一些文本PersonInfo info3;
std::string additionalText;
ss >> info3 >> additionalText; // 从字符串流中读取对象和追加的文本std::cout << "stringstream 读取的对象: " << info3._name << " " << info3._age << std::endl;
std::cout << "附加的文本: " << additionalText << std::endl;

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

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

相关文章

探秘分布式一致性(共识)算法 :Raft

1.前言 Raft 算法是 Multi-Paxos 算法的一种&#xff0c;是一种强一致性算法。核心就是通过日志复制的方式达到整个集群的副本一致。 Raft 算法的三个核心概念就是 Leader 的选举、日志复制、节点变更。本文也将从这三个方面进行探讨。之后再聊聊 Raft 算法的几个应用场景。 2.…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-27含并行连结的网络GoogLeNet

27含并行连结的网络GoogLeNet import torch from torch import nn from torch.nn import functional as F import liliPytorch as lp import matplotlib.pyplot as pltclass Inception(nn.Module):# c1--c4是每条路径的输出通道数def __init__(self, in_channels, c1, c2, c3, …

免费内网穿透工具 ,快解析内网穿透解决方案

在IPv4公网IP严重不足的环境下&#xff0c;内网穿透技术越来越多的被人们所使用&#xff0c;使用内网穿透技术的好处有很多。 1&#xff1a;无需公网ip 物以稀为贵&#xff0c;由于可用的公网IP地址越来越少&#xff0c;价格也是水涨船高&#xff0c;一个固定公网IP一年的成本…

C++ 矩阵的最小路径和解法

描述 给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。 数据范围: 1≤𝑛,𝑚≤5001≤n,m≤500,矩阵中任意值都满足 0≤𝑎𝑖,𝑗≤1000≤ai,j​≤100 要求…

基于豆瓣电影TOP250的可视化设计

本文要完成的目的&#xff0c;实现豆瓣电影TOP250的可视化 思路 讲解思路&#xff0c;采用倒推的方式&#xff0c; 首先确定可视化图表&#xff0c;也就是最终的效果。这样就能确定需要那些基础数据根据需要的数据进行按需爬取存储。 本篇文章完成前两步。可视化图表设计 和 …

搜维尔科技:「案例」NBA新科冠军与Xsens运动捕捉的缘分

北京时间昨日&#xff0c;凯尔特人在主场106比88击败独行侠&#xff0c;以总比分4比1获胜&#xff0c;夺得队史第18冠&#xff0c;超越湖人队&#xff08;17冠&#xff09;成为历史上夺冠次数最多的球队。凯尔特人队上一次夺冠还是在2007-2008赛季。 凯尔特人队主力Jayson Tat…

采用C#+uni-app 公众号预约挂号系统源码 医院公众号1分钟搞定网上“挂缴查”攻略!

采用C#uni-app 公众号预约挂号系统源码 医院公众号1分钟搞定网上“挂缴查”攻略&#xff01; 医院就诊人数持续增多&#xff0c;为保障就诊人员安全便捷就医&#xff0c;减少排队等候时间&#xff0c;进一步提升就医体验&#xff0c;医院微信公众号上线缴费、查询等功能。就诊人…

Python+Pytest+Yaml+Request+Allure框架源代码之(一)common公共方法封装

common模块&#xff1a; get_path.py&#xff1a;获取路径方法 # -*- coding: UTF-8 -*- import os# 项目根目录 BASE_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 配置文件目录 CONFIG_DIR os.path.join(BASE_DIR,config)# 测试用例文件目录 TESTCA…

高速缓存存储器(Chche)

为了解决CPU和主存之间速度不匹配的问题&#xff0c;计算机系统中引入了高速缓存&#xff08;Chche&#xff09;的概念。 基本想法&#xff1a;使用速度更快但容量更小、价格更高的SRAM制作一个缓冲存储器&#xff0c;用来存放经常用到的信息&#xff1b;这样一来&#xff0c;…

如何打包数据库文件

使用 mysqldump 命令&#xff1a; mysqldump -u username -p database_name > output_file.sql username 是数据库的用户名。database_name 是要导出的数据库名称。output_file.sql 是导出的 SQL 文件名&#xff0c;可以自定义。 示例&#xff1a; mysqldump -u root -p…

Python-正则表达式

目录 一、打开正则表达式 二、正则表达式的使用 1、限定符 &#xff08;1&#xff09;x*&#xff1a;*表示它前面的字符y 可以有0个或多个&#xff1b; &#xff08;2&#xff09;x&#xff1a;表示它前面的字符可以出现一次以上&#xff1b;&#xff08;只可以匹配多次&…

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. 泛型编程 首先让我们来思考一个问题&#xff0c;如何实现一个交换函数&#x…

晨持绪科技:开好一家抖音小店运营怎么做

在数字时代&#xff0c;抖音小店以其独特的社交媒体优势迅速崛起&#xff0c;成为许多创业者的新宠。但如何有效运营&#xff0c;却是一门学问。首要任务是确定你的小店定位&#xff0c;这关系到后续的产品选择、目标客户群及营销策略。定位明确后&#xff0c;接下来便是挑选适…

工程文档CAD转换必备!在 Java 中将 DWG 转换为 JPG

Aspose.CAD 是一个独立的类库&#xff0c;以加强Java应用程序处理和渲染CAD图纸&#xff0c;而不需要AutoCAD或任何其他渲染工作流程。该CAD类库允许将DWG, DWT, DWF, DWFX, IFC, PLT, DGN, OBJ, STL, IGES, CFF2文件、布局和图层高质量地转换为PDF和光栅图像格式。 Aspose AP…

使用 GitHub Actions 编译和发布 Android APK

使用 GitHub Actions 编译和发布 Android APK 在现代软件开发中&#xff0c;持续集成和持续部署&#xff08;CI/CD&#xff09;已成为不可或缺的一部分。对于 Android 开发者来说&#xff0c;自动化编译和发布 APK 不仅节省时间&#xff0c;还能确保每次发布的一致性。本文将介…

电脑用什么录屏?这3款软件你值得拥有

随着电脑技术的发展&#xff0c;录屏已经成为用户日常办公、学习、娱乐的重要工具之一。录屏软件种类繁多&#xff0c;功能各异&#xff0c;但如何选择合适的录屏软件成为用户面临的难题。本文将介绍电脑用什么录屏&#xff0c;并推荐三款软件&#xff0c;通过对比分析各自的特…

24.6.16

星期一&#xff1a; 补cf global round26 C2 cf传送门 思路&#xff1a;有效操作2只有一次&#xff0c;且反转后不会再出现负数&#xff0c;即后面能贡献 2^n-i个方案&#xff0c;再乘上前面 2^(k>0的次数) 代码如下&…

Golang | Leetcode Golang题解之第166题分数到小数

题目&#xff1a; 题解&#xff1a; func fractionToDecimal(numerator, denominator int) string {if numerator%denominator 0 {return strconv.Itoa(numerator / denominator)}s : []byte{}if numerator < 0 ! (denominator < 0) {s append(s, -)}// 整数部分numer…

解决安全规模问题:MinIO 企业对象存储密钥管理服务器

在强大可靠的存储解决方案领域&#xff0c;MinIO 作为持久层脱颖而出&#xff0c;为组织提供安全、持久和可扩展的存储选项。MinIO 通常负责处理关键任务数据&#xff0c;在确保高可用性方面发挥着至关重要的作用&#xff0c;有时甚至在全球范围内。存储数据的性质&#xff0c;…

Codepen Three.js环境依赖配置

Codepen Three.js环境依赖配置 前言 如果想在CodePen环境写Three.js依赖的项目&#xff0c;环境搭建可以参考该Codepen项目: Chill the lion 详细 打开设置可以看到以下配置 更多项目参考 1. Chill the Lion Chill the Lion 是一个基于 ThreeJS 制作的 WebGL 示例。它由…