【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上

浙公网安备 33010602011771号