【C++】10.深入IO[深蓝学院C++第8章]

前言

 

一.IO Stream概述

1.1流式IO与记录IO

流式IO:字节流

记录IO:如数据库,按一定的结构读写

 1.2处理的主要问题

(1)表示形式的变化:使用格式化 / 解析在数据的内部表示与字符序列间转换

(2)与外部设备的通信:针对不同的外部设备(终端、文件、内存)引入不同的处理逻辑

1.3涉及到的操作

(1)格式化/解析

(2)缓存

(3)编码转换

(4)传输

std::cout和std::cin采用模板来封装字符特性,采用继承来封装设备特性,常用的类型实际上是类模板实例化的结果。

 

二.输入与输出

2.1分类

格式化

非格式化

2.2非格式化IO

不涉及数据表示形式的变化,对人工不友好,但有时可以控制起始操作的位置、性能较好

常见输入函数:get/read/getline/gcount,如std::cin.read(reinterpret_cast<char*>(&buf),sizeof(int));

常见输入函数:put/write

2.3格式化IO

使用移位操作符来进行的输入>>与输出<<

(1)C++通过操作符重载以支持内建数据类型的格式化IO

(2)可以通过重载操作符以支持自定义类型的格式化IO

2.4格式控制

通过格式控制改变输入和输出时的具体行为

(1)可接收位掩码类型(showpos)、字符类型(fill)与取值相对随意(width)的格式化参数

(2)注意width方法的特殊性:触发后被重置,下一次输出不再有效

位掩码类型:只接收或处理指定的值,设置bit位,std::cout.setf(std::ios_base::showpos);//可在正数前面添加+号

取值相对随意:std::cout.width(10);//设置输出要占10个字符

取值为字符类型fill:std::cout.fill('.');//在空格处填充什么字符

2.5操作符manipulator

std::showpos

std::setw(10)

std::setfill('.')

简化格式化参数的设置

触发实际的插入与提取操作

2.6输入的特殊

(1)提取会放松对格式的限制

cin>>输入10或者+10,在提取时都会记性一定的格式解析、提取数据

(2)提取C风格字符串时要小心内存越界

char x[5];

std::cin >> x;

std::cout << x;

当输入字符串长度超长时由于缺少\0会导致内存操作越界

 

三.文件与内存操作

3.1文件操作

basic_ifstream/basic_ofstream/basic_fstream

文件流可以处于打开/关闭两种状态,处于打开状态时无法再次打开,只有打开时才能进行IO

输出时是先写到缓存中,ofstream文件流在析构时会自动清空缓存

3.2文件流的打开模式

 

 每种文件流都有缺省的打开方式

注意ate与app的异同,ate可以用于控制写入位置,app是只能在最后位置写入

trunc,删除文件中的已有内容

binary能禁止系统特定的转换

通过特指,避免意义不明确的流使用方式

3.3合法的打开方式组合

 

 3.4内存流

类型

basic_istringstream/basic_ostringstream/basic_stringstream

也会受打开模式影响:in/out/ate/app

获取

std::ostringstream obj1;obj1 << 1234; obj1.str();//获取内存流中的内容

使用str()方法获取底层所对应的字符串

字符串拼接

基于字符串流的字符串拼接优化操作,借助缓冲区避免string拼接的内存操作成本

std::ostringstream obj;

obj<<"Hello";obj<<" world";std::cout<<obj.str();//这样比string的+=更快一些

 

四.流的状态、定位与同步

4.1iostate

failbit/badbit/eofbit/goodbit是iostate的bit位

badbit:不可恢复的错误

failbit:读取/写入失败,流还可以继续用

eofbit:关联的输入序列已经到达文件尾

4.2检测流的状态

good()/fail()/bad()/eof()

转换为bool值

4.3注意区分fail和eof

可能会被同时设置,但二者含义不同

fail表示失败,eof表示到了结尾

转换为bool值时不会考虑eof

4.4复位流状态

clear:设置流的状态为具体的值

setstate:将某个状态附加到现有的流状态上

4.5流的异常

捕获流的异常exception

4.6流的定位

获取流位置

tellg,get获取流的位置,当前的位置

tellp,put设置流的位置

设置和获取的类型为pos_type类型

设置流位置

seekg/seekp用于设置输入\输出流的位置,以进行覆盖操作,分别有两个重载

设置绝对位置:传入pos_type进行设置

设置相对位置:通过偏移量+流位置符号的方式

(1)ios_base::beg

(2)ios_base::cur

(3)ios_base::end

4.7流的同步

基于flush/sync/unitbuf的同步

flush()用于输出流同步,刷新缓冲区,不必等缓冲区满的时候再自动刷新

sync()用于输入流同步,其实现逻辑是编译器所定义的

输出流可以通过设置unitbuf来保证每次输出后自动同步

基于绑定tie的同步

流可以绑定到一个输出流上,这样在每次输入/输出前可以刷新输出流的缓冲区

比如将cin绑定到cout上

posted @ 2023-03-01 15:53  啊原来是这样呀  阅读(32)  评论(0)    收藏  举报