IO库设施:
· istream(输入流)类型,提供输入操作;
· ostream(输出流)类型,提供输出操作;
- cin, 一个istream对象,从标准输入读取数据;
- cout, 一个ostream对象,通过用于输出程序错误消息,写入到标准错误;
- cerr, 一个ostream对象, 通常用于输出程序错误消息,写入到标准错误;
- >>运算符,用于从一个istream对象读取输入数据;
- <<运算符,用于向一个ostream对象写入输出数据;
- getline函数,从一个给定的istream读取一行数据,存入一个给定的string对象中。
一、IO类
iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。
头文件 | 类型 |
iostream | istream,wistream从流读取数据 ostream,wostream向流写入数据 iostream,wiostream读写流 |
fstream | ifstream,wifstream从文件读取数据 ofstream,wofstream向文件写入数据 iostream,wiostream读写文件 |
sstream | istringstream,wistringstream从string读取数据 ostringstream,wostringstream向string写入数据 stringstream,wstringstream读写string |
IO类型间的关系:
概念上,设备类型和字符大小都不会影响要执行的IO操作。标准库使得能忽略这些不同类型的流之间的差异,这是通过继承机制实现的。
1.1 IO对象无拷贝或赋值
不能拷贝和对IO对象进行赋值:
ofstream out1, out2;
out1 = out2; // 错误:不能对流对象赋值
ofstream print(ofstream); // 错误:不能初始化ofstream参数
out2 = print(out2); // 错误:不能拷贝流对象
1.2 条件状态
IO操作与生俱来的问题就是可能发生错误。一些错误是可恢复的,而其他错误则发生在系统深处,已经超出了应用程序可以修复的范围。下表列出了IO类所定义的一些函数和标志,帮助访问和操纵流的条件状态:
IO库条件状态 |
strm::iostate是一种机器相关的类型,提供了表达条件状态的完整功能 |
strm::badbit用来指出流已崩溃 |
strm::eofbit用来指出流到达了文件结束 |
strm::goodbit()用来指出流未处于错误状态。此处保为零 |
s.eof()若s的eofbit置位,则返回true |
s.fail()若s的failbit或badbit置位,则返回true |
s.bad()若s的badbit置位,则返回true |
s.good()若s处于有效状态,则返回true |
s.clear()若流s中所有条件状态位复位,将流的状态设置位有效。返回void |
s.clear(flags)根据给定的flags标志位,将流s中对应条件状态位复位。flage的类型为iostate,返回void |
s.setstate(flags)根据给定的flags标志位,将流s中对应条件状态位置位 |
s.rdstate()返回流s的当前条件状态,返回值类型为iostate |
查询流的状态
IO库定义了一个与机器无关的iostate类型,提供了表达流状态的完整功能。还定义了4geiostate类型的constexpr值表示特定的位模式。
- badbit表示系统级错误,如不可恢复的读写错误。通常情况下,一旦badbit被置位,流就无法再使用了。
- 在发生可恢复错误后,failbit被置位,如期望读取数值却读出了一个字符等错误。
- 如果到达文件结束位置,eofbit和failbit都会被置位。
- goodbit的值为0,表示流未发生错误。
- 如果badbit、failbit和eofbit任何一个被置位,则检测流状态的条件会失败。
标准库还定义了一组函数来查询标志位的状态。有good,bad,fail,eof四个。
管理条件状态
流对象的rdstate成员返回一个iostate,对应流当前的状态,setstate操作给定条件置位,表示发生了对应错误。clear()清除所有错误标志位。
//记住cin的当前状态
auto old_state = cin.rdstate(); //记住cin的当前状态
cin.clear(); // 使cin有效
process_input(cin); // 使用cin
cin.setstate(oldstate); // 将cin置为原有状态
// 复位failbit和badbit,保持其他标志位不变
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);
1.2 管理输出缓冲
每个输出流都管理一个缓冲区,用来保存程序读写的数据。
导致缓冲刷新的原因有很多:
- 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行;
- 缓冲区满时,而后新的数据才能继续写入缓冲区;
- 我们可以使用操作符如endl来显示刷新缓冲区;
- 在每个输出操作之后,可以用操作符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr的内容都是立即刷新;
- 一个输入流可能被关联到另一个流。这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。
刷新输出缓冲区
cout<<"hi"<<endl; // 输出hi和一个换行,然后刷新缓冲区
cout<<"hi"<<flush; // 输出hi,然后刷新缓冲区,不附加任何额外字符
cout<<"hi"<<ends; // 输出hi和一个空字符,然后刷新缓冲区
unitbuf操作符
如果想在每次输出操作后都刷新缓冲区,可以使用unitbuf操作符,他告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵副则重置流,使其恢复:
cout<< unitbuf; // 所有输出操作后都会立即刷新缓冲区
// 任何输出都立即刷新,无缓冲
cout<<nounitbuf; // 回到正常的缓冲方式
关联输入和输出流
tie有两个重载的版本,一个不带参数,返回指向输出流的指针。第二个版本接受一个指向ostream的指针将自己关联到此ostream。即x.tie(&o)将流x关联到输出流o。
二、文件输入和输出
文件模式 |
in 以读方式打开 |
out 以写方式打开 |
app 每次写操作前均定位到文件末尾 |
ate 打开文件后立即定位到文件末尾 |
trune 截断文件 |
binary 以二级制方式进行IO |
指定文件模式有如下限制:
- 只可以对ofstream或fstream对象设定out模式;
- 只可以对ifstream或fstream对象设定in模式;
- 只有当out也被设定时才可设定trunc模式;
- 只要trunc没被设定,就可以设定app模式;
- 默认情况下。即使没有指定trunc,以out模型打开的文件也会被截断;
- ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。
2.1 文件输入
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
fstream in;
in.open("1", iso::in);
if(! in.is_open())
{
cout<<"文件不存在"<<endl;
}
/*
第一种
char buf[1024] = {0};
while(in >> buf)
{
cout << buf << endl;
}
*/
/*
第二种
char buf[1024] = {0};
while(in.getline(buf, sizeof(buf)))
{
cout<<buf<<endl;
}
*/
/*
第三种
string buf;
while(getline(in, buf))
{
cout << buf << endl;
}
*/
in.close();
}
2.2 文件输出
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ostream out;
out.open("1", ios::out); // 写入文件,但会把文件中的覆盖掉
// out.open("1", ios::out | ios::app); 写入,从文件末开始
out << "111"<<endl;
// ...
out.close();
}
三、string流
相当于把string当成一个IO流操作。
略