简单的IO类继承层次结构图

IOS IOS 多继承 iostream继承关系_string

简化一下,字母后都省略一个单词stream

IOS IOS 多继承 iostream继承关系_iostream_02

很简单的继承关系istream、ostream作为基类

istream 派生出 ifstream、istringstream ; ostream 派生出 ofstream、ostringstream

同时由 istream与ostream 共同派生出 iostream

iotream 派生出 fstream、stringstream

在上述继承关系中,以前加上一个w就是其宽字符的类,eg: wistream、wstringstream

头文件

分别包含在3个头文件中

iostream //定义读写控制窗口的类型

系统已经定义好了8个输入/输出对象、包含 cin、cout、cerr、clog 以及其宽字符的版本wcin等

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

sstream //定义读写存储在内存中string对象的类型

IO对象不可复制或赋值

如果需要传递或返回IO对象,则必须传递或返回指向该对象的指针或引用

eg:
ofstream& print(ofstream &ref);

条件状态与输出缓冲区的管理

对于iostream、fstream、stringstream都适用

流条件状态

strm::iostate //用于定义条件状态

strm::badbit //用于指出被破坏的流,不可恢复(系统级故障)

strm::failbit //用于指出失败的io操作,可恢复

strm::eofbit //用于指出流已经到达文件结束符

eg:
cout << istream::badbit << istream::failbit << istream::eofbit;
//输出421表明二进制分布为111对应上述语句的位值

流方法

s.eof()、s.fail()、s.bad()、s.good()、s.clear()、s.clear(flag)、s.setstate(flag)、s.rdstate()

eg://条件状态的访问
istream::iostate oldState = cin.rdstate();//返回流当前条件状态,返回值类型 strm::iostate
cin.clear();
//process
cin.clear(oldState);
eg://多种条件状态的处理
is.setstate(ifstream::badbit | ifstream::failbit);//设置 ifstream::badbit | ifstream::failbit 条件状态(有效),对应位设置为1,其他默认为0
//process
is.clear(ifstream::badbit | ifstream::failbit);//清除 ifstream::badbit | ifstream::failbit 条件状态(失效),对应位设置为0
eg://输入管理
int iVal;
while(cin >> iVal, ! cin.eof())
{
	if(cin.bad)
		throw runtime_error("IO stream corrupted!");
	if(cin.fail())
	{
		cerr << "bad data, try again";
		cin.clear(istream::failbit);
		continue;
	}
}

缓冲区管理

输出缓冲区的刷新

flush ends(space,insert a null charater)endl(line,insert a newline)

unitbuf刷新

eg:
cout << unitbuf << "content..." << nounitbuf;

tie输入与输出

eg:
cin.tie(&cout);//这只是演示,标准库已经为我们绑定了 cin 和 cout
ostream *oldTie = cin.tie();//返回一个指向ostream对象的指针
cin.tie(0);//break tie between cin and cout
cin.tie(&cerr);//ties cin and cerr
//process
cin.tie(0);
cin.tie(oldTie);//恢复cin cout绑定

文件输入与输出

文件流对象的使用


两种使用形式


1.文件流构造函数

2.open函数

fstream特有: open、close方法

eg:
ifstream inFile("in.txt");

ofstream outFile;
outFile.open("out.txt");

检查文件打开是否成功

eg:
ifstream inFile;
string ifile("in.txt");
inFile.open(ifile.c_str());//由于历史原因,文件名用C风格字符串
if(! inFile)
{
	cerr << "error: unable to open input file: " << ifile << endl;
	return -1;
}

文件流的关闭与重新捆绑

eg:
ifstream inFile("in.txt");
inFile.close();
inFile.open("in2.txt");

清除文件流状态

eg:
while(it != files.end())
{
	ifstream input(it->c_str());//每次都生成新的流对象,所以input.good()每次都会置为true
	if(! input)
		break;
	while(input >> s)
		//process
	++it;
}
eg:
ifstream input;//只生成一次流对象
vector<string>::const_iterator it = files.begin();
while(it != files.end())
{
	input.open(it->c_str());
	if(! input)
		break;
	while(input >> s)
		//process
	input.close();
	input.clear();//更小心的处理流状态,不然的话下一次迭代不一定成功
	++it;
}

文件模式

文件输入与输出的两种形式都提供了默认实参设置文件模式

文件模式是文件属性,而不是流属性

eg:
ifstream inFile("in.txt",ifstream::in);

ofstream outFile;
outFile.open("out.txt",ofstream::app);


文件模式及其含义

//ifstream、fstream对象关系的文件能用in打开

in 读//defalut

//ofstream、fstream对象关系的文件能用下面三者打开

out 写,隐式清空文件流(丢弃该文件以前存储的所有数据,重新写入)//default相当于out | trunc

app 每次写到文件尾(可保存该文件以前存储的所有数据,在文件尾写入)相当于out | app

trunc 写,显式清空已存在文件流

//所有文件都可用下面两者打开

ate 打开后立即定位到文件尾

binary 以二进制模式进行IO操作,不解释流中字符

eg:
fstream inOut("inOut.txt",fstream::in | fstream::out);//同时in、out不清空已存在数据
fstream inOut("inOut.txt",fstream::in | fstream::out | fstream::trunc);//指定trunc时,无论是否指定in都清空已存在数据
eg://打开并检查输入文件
ifstream& openFile(ifstream &in,const string &fileName)
{
	in.close();
	in.clear();
	in.open(file.c_str());
	return in;//无论成功与否都返回
}

字符串流

字符串流对象的使用

eg:
string line,word;
while(getline(cin,line))//read a line from the input into string:line
{
	//per-line process
	istringstream stream(line);//bind to stream to the line we read
	while(stream >> word)//read a string:word from string:line
		//per-word process
}

stringstream提供的转换和格式化

eg:
int iVal1 = 512,iVal2 = 1024;
ostringstream formatMsg;//写到
formatMsg << "Val1: " << iVal1 << "\n" << "Val2: " << iVal2 << "\n";

istringstream inputIString(formatMsg.str());//读入
string dump;
inputIString >> dump >> iVal1 >> dump >> iVal2;
cout << iVal1 << " " << iVal2 << endl;