IO库

一、IO类:

IO库类型和头文件:

iostream 定义了用于读写流的基本类型;

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

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

为了支持使用宽字符的语言,标准库定义类型和函数的名字以一个w开始。

头文件 类型
iostream istream,wistream  从流读取数据
  ostream,wostream  向流中写入数据
  iostream,wiostream  读写流
fstream ifstream,wifstream  从文件读取数据
  ofstream.wofstream  向文件写入数据
  fstream,wfstream  读写文件
sstream istringstream,wistringstream  从string读取数据
  ostringstream.wostringstream  向string写入数据
  stringstream,wstringstream  读写string

IO类型间的关系:

标准库通过继承机制,利用模板,使设备的类型和字符大小都不会影响我们执行IO操作。

ifstream和istringstream都继承自istream。

 

1.1、IO对象无拷贝或赋值

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

由于不能拷贝IO对象,所以进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能使const的

 

1.2、条件状态

strm::iostate strm是一种IO类型。iostate是一种机器相关的类型,提供了表达条件状态的完整功能;
strm::badbit  用来指出流已经崩溃;
strm::failbit 用来指出一个IO操作失败了;
strm::eofbit 用来指出流到达了文件结束;
strm::goodbit 用来指出流没有处于错误状态,此值保证为零;
s.eof() 若流s的eifbit位置,则返回true;
s.fail()

若流s的failbit或badbit位置,则返回true;

s.good()

若流处于有效状态,则返回true;
s.bad() 若流处于badbit位置,则返回true;
s.clear() 将流s中所有条件状态位复位,将流的状态位设置为有效,返回void;
s.clear(flags) 根据给定的flags标志位,将流s中对用条件状态位复位;
s.setstate(flags) 根据给定的flag标志位,将流s中对应条件状态位置位;
s.rdstate() 返回流s的当前条件状态。

代码通常应该在使用一个流之前检查它是否处于良好状态。确定一个流对象的状态的最简单的方法是将它当作一个条件来使用:

while(cin >> word)
    //ok:读操作成功

 

查询流的状态:

IO库定义了一个与机器无关的iostate类型,它提供了表达流状态的完整功能。IO库定义了4个iostate类型的constexpr值。

badbit表示系统级错误,如不可恢复的读写错误,流无法再使用;

failbit1表示可恢复的读写错误,流还是可以用的;

如果到达文件结束位置,eofbit和failbit都会被置位;

goodbit的值位0,表示流未发生错误。

如果badbit和failbit、eofbit任一被置位,则检测流状态的条件会失败。

实际上,我们将流当作条件使用的代码就等价于!fail()。

 

管理条件状态:

rdstate返回一个iostate的值,对应流的当前状态;

setstate操作将给定条件位置为,表示发生了对应的错误。

 

1.3、管理输出缓冲

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

文本串有可能立即打印出来,也有可能被操作系统保存在缓冲区中,随后打印出来。

有了缓冲机制,操作系统就可以将程序的多个输出操作组合程单一的系统级写操作。

其中,导致缓冲刷新的原因有:

  • 程序正常结束;
  • 缓冲区满;
  • 使用操纵符endl;
  • 在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态,来清空缓冲区;
  • 一个输出流可能被关联到另一个输出流。

 

刷新输出缓冲区:

操纵符endl,完成换行并刷新缓冲区的工作;

操纵符flush,刷新缓冲区,但不输出任何额外的字符;

操纵符ends,向缓冲区插入一个空字符,然后刷新缓冲区。

cout << "hi!" << endl;
cout << “hi!” << flush;
cout << "hi!" << ends;

 

unitbuf操作符:

如果想在每次操作后都刷新缓冲区,则我们可以使用unitbuf操纵符。它告诉缓冲区,在每一次操作之后都进行一次flush操作。而nounitbuf操纵符,则重置流,恢复使用正常的系统管理缓冲区刷新。

cout << unitbuf;  //所有输出操作后都会立即刷新缓冲区
..................//任何输出都立即刷新,无缓冲
cout  << nounitbuf;//恢复正常的缓冲方式

 

关联输入和输出流

当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流,

tie有两个重载版本:

  • 不带参数,返回指向输出流的指针。如果本对象关联到一个输出流,则返回的就是指向这个流的指针。如果没有关联,则返回空指针;
  • 带参数,将自己关联到输出流。即,x.tie(&o)将流x关联到输出流o。

 

2、文件输入输出

fstream fstrm 创建一个未绑定的文件流。fstrm时头文件fstream定义的一个类型。
fstream fstrm(s) 创建一个fstream,并打开名为s的文件。s可以是string类型,或者是一个指向C风格字符串的指针。
fstream fstrm(s,mode)

与前一个构造函数类似,但按指定的mode打开文件。

fstrm.open(s) 打开名为s的文件,并将文件与fstrm绑定。s可以是一个string或一个指向C风格字符串的指针。
fstrm.close() 关闭与fstrm绑定的文件。返回void
fstrm.is_open() 返回一个bool值,指出与fstrm关联的文件是否成功打开或者尚未关闭。

2.1、使用文件流对象

用fstream替代iostream&

成员函数open和close

 2.2、文件模式

in 以读方式打开
out 以写方式打开
app 每次写操作钱均定为到文件末尾
ate 打开文件后立即定位到文件末尾
trunc 截断文件
binary 以二进制方式进行IO

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

保留被ofstream打开的文件中已有数据的唯一方法是显式指定app或in模式。

 

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

对于一个给定流,每当打开文件时,都可以改变其文件模式。

 

3、string流

sstream strm

strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型。

sstream strm(s) strm是一个sstream对象,保存string s的一个拷贝。
strm.str() 返回strm所保存的string的拷贝。
strm.str(s) 将string s 拷贝到strm中,返回void。

3.1 使用istringstream

3.2使用ostringstream

上一篇:最低公共祖先(LCA)


下一篇:第八章 IO库