C++系统学习之八:IO库

Wesley13
• 阅读 487

  新的C++标准中有三分之二的内容都是描述标准库。接下来重点学习其中几种核心库设施,这些是应该熟练掌握的。

  标准库的核心是很多容器类(顺序容器和关联容器等)和一簇泛型算法(该类算法通常在顺序容器一定范围内的元素上或其他类型的序列上进行操作)。

  该篇主要学习IO库。

  C++语言不直接处理输入输出,而是通过一簇标准库中的IO库来处理。IO库定义了读写内置类型值的操作。

1、IO类

  为了处理不同的种类的IO操作,定义了:iostream(用于读写流的基本类型)、fstream(读写命名文件的类型)、sstream(读写内存string对象的类型)。

C++系统学习之八:IO库

其中后面以w开头的是宽字符版本。

IO类型间的关系

继承机制:ifstream和istringstream都是继承自istream,上述所有的IO库类型之间都存在这种继承关系。

下面介绍的标准库流特性都可以无差别地应用于普通流、文件流和string流,以及它们的宽字符版本。

1.1 IO对象无拷贝或赋值

不能拷贝或对IO对象赋值

ofstream out1,out2;
out1=out2;    //错误,不能对流对象赋值
ofstream print(ofstream);    //错误,不能初始化ofstream参数
out2=print(out2);        //错误,不能拷贝流对象

因为不能拷贝IO对象,因此不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const。

1.2 条件状态

IO操作可能会发生错误,IO类通过定义一些条件状态来显示IO对象的状态,使用户知道流的当前状态。

C++系统学习之八:IO库

C++系统学习之八:IO库

由于流操作可能发生的错误,因此,代码通常应该在使用一个流之前检查它是否处于良好状态,最简单的方法是将它当作一个条件来使用。

while(cin>>word)
{
    ......
}

查询流的状态

有时候不仅仅需要知道流是否有效,还要知道到底是什么原因导致流失效,IO库定义了一个与机器无关的iostate类型,它提供了表达流状态的完整功能。这个类型应作为一个位集合来使用。

使用good或fail是确定流的总体状态的正确方法。上述将流作为条件使用的代码等价于!fail()。

while(cin>>word)
{
    ......
}

==================

cin >> s;
while (!(cin.fail()))
{

}

管理条件状态

流对象的rdstate成员返回一个iostate值,对应流的当前状态。setstate操作将给定条件位置位,表示发生了对应错误。clear成员是一个重载的成员。有一个无参数的版本,清除所有错误标志位。

auto old_state=cin.rdstate();    //记住cin的当前状态
cin.clear();    //清除所有错误
process_input(cin);    //使用cin
cin.setstate(old_state);    //将cin置为原有状态

 1.3 管理输出缓冲

每个输出流都管理一个缓冲区,用来保存程序读写的数据。

刷新输出缓冲区

已经使用过操纵符endl,它完成换行并刷新缓冲区的工作。IO库还有两个类似的操纵符:flush和ends。flush刷新缓冲区,但不输出任何额外的字符;ends向缓冲区插入一个空字符,然后刷新缓冲区。

unitbuf操纵符

unitbuf每次输出操作后都刷新缓冲区。它告诉流在接下来的每次写操作之后都进行一次flush。而nounitbuf操纵符则重置流,使其恢复正常的系统管理的缓冲区刷新机制。

cout<<unitbuf;    //所有输出操作后都会立即刷新缓冲区

cout<<nounitbuf;    //回到正常的缓冲方式

2、文件输入输出

 头文件fstream定义了三种类型来支持文件IO:ifstream、ofstream、fstream。

fstream除了继承自iostream类型的行为之外,fstream还定义了一些自己专有的操作。这是其他IO类型所没有的。

C++系统学习之八:IO库

2.1 使用文件流对象

用fstream代替iostream&

在使用iostream的地方,可以用fstream代替调用,因为fstream是从iostream继承来的。

成员函数open和close

可以先定义一个空文件流对象,然后用open将其与文件关联起来。

如果调用open失败,则failbit会被置位,因此进行open是否成功的检测是一个好的习惯。

ofstream out;
out.open("1.txt");
if(out)
.......

将文件流对象绑定到另一个文件之前,需要先close已经关联的文件,然后再关联新的文件。

自动构造和析构

当一个fstream对象被销毁时,close会自动被调用。

2.2 文件模式

每个流都有一个关联的文件模式,用来指出如何使用文件。

C++系统学习之八:IO库

指定文件模式有如下限制

  • 只可以对ofstream和fstream对象设定out模式
  • 只可以对ifstream和fstream对象设定in模式
  • 只有当out也被设定时才可设定trunc模式
  • 只要trunc没被设定,就可以设定app模式。在app模式下,即使没有显式指定out模式,文件也总是以输出方式被打开
  • ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用

每个文件流类型都定义了一个默认的文件模式,ifstream是in,ofstream是out,fstream是in和out

以out模式打开文件会丢弃已有数据

默认情况下,打开一个ofstream时,文件的内容会被丢弃。阻止一个ofstream清空给定文件内容的方法是同时指定app模式。

ofstream app("file",ofstream::app);    
ofstream app2("file",ofstream::out | ofstream::app); 

每次调用open时都会确定文件模式

ofstream out;
out.open("file1");    //模式隐含设置为输出和截断
out.close();
out.open("file2",ofstream::app);   //模式为输出和追加
out.close();

 通常情况下,out模式意味着同时使用trunc模式,因此,file1的文件的内动将被清空。

每次打开文件时,都要设置文件模式,可能是显式地设置,也可能是隐式地设置,当程序未指定模式时,就使用默认值。

3、string流

 sstream头文件定义了三个类型来支持内存IO,这些类型可以向string读写数据,string像是一个IO流一样。

  • istringstream
  • ostringstream
  • stringstream

上述三种都继承自iostream。同样的,除了继承来的操作,其也定义了自己特有的操作。

C++系统学习之八:IO库

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
2年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这