当前位置: 首页 > news >正文

IO流的简单介绍

(PS:这得学好,不然到Linux那边会蒙,还是得重新学)

什么是IO流?

C++ IO流(Input/Output Stream) 是C++标准库中用于处理输入和输出操作的核心机制,通过“流”(数据的有序序列)的抽象概念,实现数据在程序与外部设备(如键盘、屏幕、文件等)之间的传输。

核心本质:

- 流的抽象:将数据传输过程模拟为“水流”,数据从“源”(如文件、键盘)流向程序(输入流),或从程序流向“目的地”(如屏幕、文件)(输出流)。

- 设备无关性:无论操作的是键盘、屏幕还是文件,都使用统一的接口(如 << 、 >> 运算符),无需因设备不同修改核心代码。

在此之前,我们先来了解一些关于C语言的IO(printf,scanf)

scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中。

printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)

其中,在它们进行数据的输送的过程中,并不是已经发过去的,而是通过输入/输出缓冲区来进行传输的!

为什么要有缓冲区呢?

平衡高速CPU与低速I/O设备(如磁盘、键盘、显示器)的速度差异,减少I/O操作次数,从而提升程序整体效率。

屏蔽掉低级I/O的实现:低级I/O的实现依赖操作系统本身内核的实现,所以如果能够屏蔽这部分的差异,可以很容易写出可移植的程序。
可以使用这部分的内容实现“行”读取的行为,计算机中没有行的概念的,这个缓存区就充当了行的条件,当读完缓冲区里面的内容,就当作一行。

具体的优势:

其具体作用可分为以下3点:(先了解,后面我们讲解Linux的时候会具体讲解的,到时候就会更加理解下面的意思的!)

1. 降低硬件操作开销:I/O设备(尤其是磁盘)的单次读写操作存在固定“启动成本”(如磁头寻道、电机转动)。缓冲器会先暂存数据,积累到一定量后再一次性与设备交互,大幅减少操作次数,降低硬件资源消耗。

2. 减少CPU等待时间:若没有缓冲,CPU每次执行I/O操作时都需等待设备响应(“阻塞等待”),导致CPU资源闲置。有缓冲时,CPU只需将数据写入/读取到缓冲器(高速内存操作),即可继续执行其他任务,后续由操作系统或硬件自行完成缓冲器与I/O设备的同步。

3. 优化数据传输效率:多数I/O设备(如网络、磁盘)更适合“批量传输”而非“字节级传输”。缓冲器能将零散的小数据块整合为连续的大数据块,匹配设备的传输特性,减少数据传输中的冗余开销。

流的特性

有序连续、具有方向性

eg:C++中,我们从键盘输入数据,显示器上显示出来,这也是一种流。

C++IO流

C++中,有专门的流的库,即IO流

1. 头文件  <ios> 
- 核心类: ios_base 、 ios 

- 作用:提供IO流的基础类和状态管理功能(如格式标志、错误状态等),是其他IO流类的基类,不直接用于普通IO操作,主要为上层类提供底层支持。

2. 头文件  <istream> 
- 核心类: istream 

- 作用:定义输入流的接口,提供从流中读取数据的功能, cin  是其常用对象(用于标准输入,如键盘输入)。


3. 头文件  <iostream> 
- 核心类: iostream (由  istream  和  ostream  派生)

- 作用:同时支持输入和输出操作,整合了  <istream>  和  <ostream>  的功能。常用对象有  cin (输入)、 cout (标准输出,如屏幕打印)、 cerr (标准错误输出,无缓冲)、 clog (标准错误输出,有缓冲)。

4. 头文件  <fstream> 
- 核心类: ifstream (文件输入流)、 ofstream (文件输出流)、 fstream (文件读写流)、 filebuf 

- 作用:用于文件的输入输出操作,支持对磁盘文件的读取、写入和修改。例如, ifstream  可打开文件并读取内容, ofstream  可创建或覆盖文件并写入内容。


5. 头文件  <sstream> 
- 核心类: istringstream (字符串输入流)、 ostringstream (字符串输出流)、 stringstream (字符串读写流)、 stringbuf 

- 作用:用于字符串的输入输出操作,可将字符串当作流来处理,实现字符串与其他类型数据的转换(如将字符串中的数字提取为整数)。

ps:

1.在使用时候必须要包含文件并引入std标准命名空间

2.cin:标准输入:即程序代码->硬件设备

3.cout标准输出:即硬件设备->程序代码。

4.cout、cerr、clog是ostream类的三个不同的对象,因此这三个对象现在基本没有区别,只是应用场景不同

5.cin的特性:cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。(这就是为什么我们在输入数据没按下回车时,它会阻塞住,即在缓冲区那里阻塞住)。

6.输入的数据类型必须与要提取的数据类型一致,否则出错

证明:

ps:大概了解一下:状态:goodbit,eofbit,failbit,badbit

7.空格和回车都可以作为数据之间的分格符

但是,对于字符串的话,我们无法使用cin了,因为字符串我们无法判断空格是字符还是分隔符。所以我们一般不用这个

那么我们会使用哪个呢?

单字符:cin(跳过前导的空格,回车,读取第一个非空白字符),cin.get()(读取输入缓冲区中的第一个字符,包括空格,回车)

含空格字符串:getline(cin,str)(包<string>头文件)(会读取一整行内容,包括空格,一直到遇到回车为止)

8.cin和cout可以直接输入和输出内置类型数据,原因:标准库已经将所有内置类型的输入和

输出全部重载了

9.自定义类型数据需要自己重载。

看看我们写OJ的时候,

对于IO类型的算法,一般都需要循环输入:

输出:严格按照题目的要求进行,多一个少一个空格都不行

它在汇编那里实质上也调了三个operator();

调用的是operator>>,返回值是istream类型的对象,那么这里可以做逻辑条件值,源自于istream的对象又调用了operator bool,operator bool调用时如果接收流失败,或者有结束标志,则返回false。

文件IO

文件内容的数据格式分为二进制文件和文本文件

步骤:

1. 定义一个文件流对象

ifstream ifile(只输入用)
ofstream ofile(只输出用)
fstream iofile(既输入又输出用)

2. 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系

3. 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写

4. 关闭文件

fwrite:二进制读写

当在文件中建好的时候,打开发现是一串我们看不懂的字符,内存中与文件中的表达式是不一样的,内存中是以12字节存储的,而且存的是补码。

fputs:以字符串读写

用这个接口,打开文件时就可以正常看懂了。

atoi

字符串转整形

to_string

整形转字符串,头文件string

ofstream

从文件写数据

注意:

这里如果用string的话会坑:

1. 字符数组( char[] )的“安全”性
字符数组是把字符串的每个字符直接存在数组里(类似“把内容装在盒子里”)。不管字符串多长,数据本身都“老老实实”存在数组的内存空间中。所以进程 A 把字符数组的内容写出去,进程 B 读的时候,能直接拿到“实实在在的字符串内容”。


2.  string (C++ 标准库的字符串类)的“特殊”存储
string  内部不是简单地把所有字符存在自己的“小盒子”里:
- 当字符串比较短时(不同编译器/环境有差异,比如 Linux 和 Windows 表现不同), string  可能会用“内部缓冲区”直接存字符(类似字符数组的行为)。

- 但当字符串比较长时, string  会“偷懒”:它不在自己的内存里存所有字符,而是只存一个“指针”,指向另一片内存(堆上)里真正的字符串内容。


3. 进程间二进制读写的“矛盾点”
进程是相互独立的内存空间(一个进程的“地址”,在另一个进程里是“无效地址”)。
如果用  string  做进程间二进制读写:
- 你写出去的,其实是  string  内部的“指针”(以及一些辅助信息),不是真正的字符串内容。

- 另一个进程读的时候,拿到的是“上一个进程里的指针”,但这个指针在自己的内存空间里根本无效,就像“拿着别人家里的钥匙开自己家的门”,完全读不出正确内容——这就是所谓“相当于内存指针出问题了”。


4. 结论:二进制读写别用  string  直接传

如果要在进程间传递字符串的二进制数据,不能直接用  std::string  或  string  类对象来读写。因为它存的“指针”在跨进程时毫无意义,应该用**字符数组( char[] )**或者“手动管理的连续内存”来存储字符串内容,再进行进程间传输。

ifstream

从文件读数据

总结:

特性ifstreamofstream
核心功能  从文件读数据 向文件写数据
默认打开模式 ios::in(读取)    ios::out  (写入,覆盖原文件)
典型使用场景 读取配置文件、日志文件内容等      生成日志、保存计算结果等
操作符使用   用 >> 读数据   用 << 写数据

istringstream

头文件#include<sstream>

字符串输入流类,用于从字符串中提取数据

区别:

工具    操作对象    核心能力
istringstream字符串  从字符串中提取多类型数据
cin标准输入(控制台) 从控制台提取数据
ifstream文件    从文件中提取数据

ostringstream

头文件#include<sstream>

字符串输出流类,用于向字符串写入(拼接)数据。

stringstream

头文件#include<sstream>

 

在C语言中,如果想要将一个整形变量的数据转化为字符串格式,如何去做?

1. 使用itoa()函数:

2. 使用sprintf()函数

但是两个函数在转化时,都得需要先给出保存结果的空间,那空间要给多大呢,就不太好界定,而且转化格式不匹配时,可能还会得到错误的结果甚至程序崩溃

特性:stringstream结合了上面istringstream和ostringstream的特性。

所以它也可以进行字符串拼接,拆分。

另外,它还可以进行数据类型转化(字符串转整数)

1.stringstream实际是在其底层维护了一个string类型的对象用来保存结果。

2. 多次数据类型转化时,一定要用clear()来清空,才能正确转化,但clear()不会将stringstream底层的string对象清空。

3. 可以使用s. str("")方法将底层string对象设置为""空字符串。

4. 可以使用s.str()将让stringstream返回其底层的string对象。

5. stringstream使用string类对象代替字符数组,可以避免缓冲区溢出的危险,而且其会对参

数类型进行推演,不需要格式化控制,也不会出现格式化失败的风险,因此使用更方便,更安全。

好了,关于IO的简单了解就到这里,以后用到再回顾就行了。希望大家一起进步!

最后,到了本次鸡汤环节:

贴上最近看到一句话:

努力这件事,绝不是摇旗呐喊、激情澎湃,他就是枯燥乏味的无限循环,当你真正适应了这种状态的时候,你就会发现你与周围的人变得不一样了,加油。

http://www.dtcms.com/a/391408.html

相关文章:

  • 【AI论文】SAIL-VL2技术报告
  • 基于 SSM(Spring+SpingMVC+Mybatis)+MySQL 实现(Web)软件测试用例在线评判系统
  • 【2/20】理解 JavaScript 框架的作用:Vue 在用户界面中的应用,实现一个动态表单应用
  • Android冷启动和热启动以及温启动都是什么意思
  • Java数据结构 - 单链表的模拟实现
  • git忽略CRLF警告
  • 不用手也能玩手机?多代理协作框架让 APP 自动执行任务
  • 装备制造企业支撑智能制造的全生命周期数据治理实践
  • 【论文阅读 | AAAI 2025 | Mamba YOLO: 基于状态空间模型的目标检测简单基线​​】
  • AdMergeX与小川科技最右App合作案例入选中国信通院“高质量数字化转型典型案例集”
  • LoadBalancer配置
  • 国内外主流开源密码库:演进背景、国密适配与企业维护挑战
  • 车规级MCU在特种车辆车身控制中的应用研究
  • 深度学习基本模块:GRU 门控循环单元
  • 通过Keepalived+LVS搭建NAT模式的高可用集群系统保姆级教程
  • 设备硬件能力调用:传感器、蓝牙与定位
  • 完全二叉树的链式创建以及遍历
  • 数据结构——二叉树和BST(2)
  • 一文解码百度地图ETA
  • 好题推荐-剑指S10
  • Python 中的魔术方法(Magic Methods)
  • JavaScript事件循环机制----event loop
  • C++编程学习(第33天)
  • 伺服上位机展示
  • Class62 优化算法
  • 电气专业科研怎么入门?电气仿真入门秘籍
  • 软考-系统架构设计师 基于构件的软件工程详细讲解
  • MCP 项目标准管理工具 v1.1.0 发布:新增 API 调试功能,助力 AI 辅助开发标准化
  • Linear Algebra in Competitive Programming
  • Decision Trees vs Neural Networks|决策树 vs 神经网络