IO库


c++ 语言中不直接处理输入和输出,而是通过一族定义在标准库中的类型来处理IO,这些类型支持从设备读取数据、向设备写入数据的IO操作。设备可以是文件、控制台窗口等。还有一些IO运行内存IO,即可以从string中读写数据。

IO库

IO类

最开始接触的c++ 中的io是我们从控制台接受输入的istream和输出到控制台中的ostream。除了基本的istream和ostream以外标准库中还定义了如下的基本类型

iostream 用于读写流的基本类型

  1. istream、wistream: 从流读取数据
  2. ostream、wostream: 向流写入数据
  3. iostream、wiostream:从流中读写数据

fstream 定义了读写命名文件的类型

  1. ifstream、wifstream: 从文件中读写数据
  2. ofstream、wofstream: 向文件中写入数据
  3. fstream、wfstream: 读写文件

sstream 定义了读写内存string对象的类型

  1. istringstream、iwstringstream: 从string中读取数据
  2. ostringstream、owstringstream: 向string中写入数据
  3. stringstream、wstringstream: 读写string

其中带w的都是款字节版本

无法对io对象进行拷贝或者赋值、因此在函数中无法返回IO类型也无法传递IO类型,只能使用IO类型的引用

读写一个IO对象会改变其状态,所以在函数中传递和返回IO的对象不能是const的

一个流如果发生错误,其上后续的IO操作都会失败。只有当一个IO流处于无错误状态时,我们才能从它读取数据。因此代码通常应该在使用一个流之前检查它是否处于良好状态,确定一个流对象的状态最简单的方式是将它作为一个条件来使用。

作为条件使用只能告诉我们流是否有效,而无法告诉我们具体发生了什么。IO库定义了一组与机器无关的iostate类型,这个类型中使用二进制位来表示每种状态。目前定义了4种错误类型:

  1. badbit: 流崩溃
  2. failbit: IO操作失败
  3. eofbit: 流到达了文件结束位置
  4. goodbit: 流未处于错误状态

在实际使用时可以将具体值与这些预定义的值做位与运算,得到具体的原因

流对象的rstate 成员返回当前流的状态,setstate用来设置流状态。clear不带参用来清理所有错误标志位。clear的带参版本接受一个iostate值,表示流的新状态

io操作比较耗时,所以操作系统为了效率会提供缓冲机制。输入输出并不是立即执行的,操作系统提供了一个缓冲区,在适当的实际会使用缓冲区的数据,统一执行输入输出操作。导致刷新的原因有很多:

  1. 程序正常结束,在main函数执行return时,会进行刷新操作
  2. 缓冲区满时,会进行换新操作
  3. 程序中使用操作符例如endl来显式的刷新缓冲区
  4. 输出操作结束后,使用操作符unitbuf 设置流的内部状态来清空缓冲区,默认情况下cerr 是设置了unitbuf 的,因此cerr的内容都是实时刷新的
  5. 一个输出流被关联到另一个输出流。当读写被关联到另一个流时,关联到的流的缓冲区会被刷新

除了使用endl、flush、ends 都可以来刷新缓冲区。endl在刷新的同时会插入换行符,flush则不添加任何字符,ends会添加一个空字符

如果想在每次输出后都刷新缓冲区,可以使用unitbuf 操作符,它告诉流,每次执行写操作之后都进行一个flush操作

cout << unitbuf;
cout << nounitbuf;

如果程序崩溃,缓冲区是不会被刷新的

标准库是将cin和cout关联到一起了,所以每次执行cin都会导致cout的缓冲区被刷新

可以使用tie 方法将自身关联到另一个流上。
tie 带参数的版本,需要传入一个指向ostream 的指针,将自己关联到这个ostream中
tie 不带参数的版本用来查询自身关联到了哪个输出流上,返回对应输出流的指针,如果未被关联,则返回空指针
每个输入流最多只能关联到一个输出流,但是多个输入流可以关联到同一个ostream

文件IO

当我们要读写一个文件时可以使用文件流对象

ifstream in(ifile); //传入文件名,构造一个ifstream 并打开文件
ofstream out; //定义一个文件输出流,这个流不关联到任何文件

当我们定义了空的文件流对象后可以使用open函数将对象和文件关联起来。可以手动调用close函数关闭文件。也可以在fstream对象被销毁时由它的构造函数自动调用close

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

  1. in: 以读的方式打开
  2. out: 以写的方式打开
  3. app: 每次写操作前均定位到文件尾部
  4. ate: 每次打开文件后立即定位到文件尾部
  5. trunc: 截断文件
  6. binary:以二进制的形式打开文件

string 流

当我们的某些工作是对文本进行处理,而其他一些工作是处理行内的单词时通常可以使用 istringstream

即要在一行字符串中取出单个单词时可以使用字符串流