标准IO库

一、面向对象的标准库

C++的输入输出都是由标准库提供。标准库中还定义了一族类型,支持对文件和控制窗口等设备的读写。

比如说,IO类型在三个独立的头文件中定义:

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

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

sstream定义的类型则用于读写存储在内存中的string对象。

IO标准库类型和头文件
头文件 类型
iostream istream从流中读取
ostream 写到流中去
iostream 对流进行读写;从istream和ostream派生而来

fstream ifstream从文件中读取;由istream派生而来
ofstream 写到文件中去;由ostream派生而来
fstream 读写文件;由iostream派生而来

sstream istringstream从string对象中读取;由istream派生而来
ostream stream写到string对象中去;由ostream派生而来
stringstream 对string对象进行读写;由iostream派生而来

程序可以对控制窗口,已命名的文件和内存进行IO。

注意:1.迄今所描述的流类读写的都是由char类型组成的流。

2.标准库类型不允许复制和赋值操作(error:ofstream out1=out2)


二、条件状态

我们需要知道IO标准库是如何管理其缓冲区及其流状态的相关内容。那以下的条件状态就是用来标记给IO对象是否处于可用状态或者是碰到了哪些特定的错误。

IO标准库的条件状态
strm::iostate 机器相关的整型名,由各个iostream类定义,用于定义条件状态
strm::badbit strm::iostate类型的值,用于指出被破坏的流
strm::failbit strm::iostate类型的值,用于指出失败的IO操作
strm::eofbit strm::iostate类型的值,用于指出流已经到达文件结束符
s.eof() 如果设置了流s的eofbit值,则函数返回true
s.fail() 如果设置了流s的failbit值,则函数返回true
s.bad() 如果设置了流s的badbit值,返回true
s.good() 如果流s处于有效状态,返回true
s.clear() 将流s中的所有状态值都重设为邮箱状态
s.clear(flag) 将流s中的某个条件状态设置为有效
s.setstate(flag) 给流s添加指定状态。
s.rdstate() 返回流s的当前条件

// C++文件读写.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
int main()
{
	ofstream fin;
	fin.open("file1.txt");//创建文件file1.txt
	int row,col,i,j,number;
	cout<<"Enter data row and col:";
	cin>>row>>col;
	//按照行列写入数据到 file.txt中
	cout<<"Enter data:"<<endl;
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			cin>>number;
			fin<<number<<" ";//写入数据到文件
		}
		fin<<"\n";
	}
	fin.close();
	//写入数据完毕
	ifstream infile;
	infile.open("file1.txt");//打开文件file1.txt
	fin.open("file2.txt");//创建文件file2.txt
	if(!infile.is_open())
	{//若打开失败
		cout<<"open file1 failed!"<<endl;
		exit(EXIT_FAILURE);
	}
	//infile>>number;//开始从文件中读取数据
	int sum=0,count=0;//sum用于保存每一行的和,count用于区分一行结束,以便计算均值
	sum+=number;
	while(infile>>number,!infile.eof())
	{//没到文件尾
		++count;
		if(count%col==0)
		{//一行读取完毕
			fin<<sum<<" "<<(double)sum/col<<endl;//将计算结果写入file2.txt
			sum=0;//将保存行的和置为零
		}
		else
		{
			infile>>number;//读取数据到number中
			sum+=number;//实现累加求和
		}
	}
	infile.close();
	fin.close();
	//写入数据读数据完毕,关闭文件流
	return 0;
}



有个疑问:绿色标注的两个地方,效果不一样。

条件状态到底有什么用?你自己想想,如果流处于错误状态,你是不是应该知道是哪类错误,是IO设备错误还是其他错误。

1.条件状态

IO类定义了三个iostate类型的常量值

badbit:系统级故障,无法恢复的读写错误。表示流已经不能使用

failbit:可恢复的故障

eofbit:遇到了文件结束符

2.流状态的查询与控制

int ival;
while(cin>>ival,!cin.eof()){
        if(cin.bad())//输入流corrupted
             throw runtime_error("IO stream corrupted");
        if(cin.fail()){
              cerr<<"bad data, try again";               cin.clear(istream::goodbit);
              cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');//ignore bad input
              continue;
         }
         // ok to process ival
}

3.条件状态的访问

istream::iostate old_state = cin.rdstate();

cin.clear();

process_input();     //use cin

cin.clear(old_state);  // now rest cin to oldstate

4.多种状态的处理

is.setstate(ifstream::badbit | ifstream::failbit)

将对象is的failbit和badbit位同时打开。


三、输出缓冲区的管理

每个IO对象管理一个缓冲区,用于存储程序读写的数据。

下面几种情况将导致缓冲区内容被刷新,即写到控制设备或文件中。

1)程序正常结束。main函数一部分,缓冲区清空。

2)缓冲区满了,在写入之前刷新;

3)用操作符显示的刷新缓冲区,如endl;

4)每次输出操作执行完后,用unitbuf操作符设置流的内部状态,清空缓冲区;

5)可将输出流与输入流关联起来(tie)。这样,读输入流的时候刷新其相关的输出缓冲区。

1.输出缓冲区的刷新

cout<<"hi"<<flush;//flush buffer不添加数据
cout<<"hi"<<ends;//添加一个null,flush buffer
cout<<"hi"<<endl;//插入一个新行,flush buffer

2.unitbuf操作符

cout<<unitbuf<<"first"<<"second"<<nounitbuf
等价于
cout<<"first"<<flush<<"second"<<flush
nounitbuf用于将流恢复为使用正常的,由系统管理的缓冲区刷新方式。

3.将输入和输出绑在一起

一般用tie函数。


四、文件的输入和输出

fstream头文件定义了三种支持文件IO的类型:

1) ifstream,由istream派生而来,提供读文件的功能;

2) ofstream,由ostream派生而来,提供写文件的功能;

3) fstream,由iostream派生而来,提供读写同一个文件的功能。

另外,fstream类型还自定义了两个新操作-open()和close()

<一> 文件流对象的使用

将要定义的对象和需要读写的文件(ifile和ofile)进行绑定。

ifstream infile(ifile.c_str());
ofstream outfile(oflile.c_str());
或者
ifstream infile;
ofstream outfile;
infile.open("in");
outfile.open("out");
注意:IO标准库使用的是C风格的字符串,而不是C++ string类型的字符串。因此你需要通过c_str()进行转换。

1.检查是否成功

if(!infile){
      cerr<< "error: unable to open input file:"
             <<ifile<<endl;
       return -1;
}
2.将文件流与新文件重新捆绑

ifstream infile("in");
infile.close();
infile.open("next");
3.清除文件流的状态

while( it != files.end){
       ifstream input(it->c_str());
       // if the file ok, process input
       if(!input)
             break;
       while(input>>s)
             process(s);
       ++it;
}
其中,需要读取vector对象中的files
ifstream input;
vector<string>::const_iterator it=fiels.begin();
while( it != files.end()){
       input.open(it->c_str());
       // if the file ok, process input
       if(!input)
             break;
       while(input>>s)
             process(s);
       input.close();
       input.clear();
       ++it;
}
注意:
1)定义一个IO对象;
2)通过close()和clear()操作关闭和清空文件流;
3)如果需要重用文件流读写多个文件,必须在读另一个文件之前调用clear清除该流的状态。
<二>文件模型
文件模式
in 打开文件做读操作out                    打开文件做写操作app在每次写之前找到文件尾ate打开文件后立即将文件定位到文件尾trunc打开文件时清空已存在的文件流binary以二进制模式进行IO操作
例如:
ofstream outfile1("file1",ofstream::out | ofstream::trunc) 
ofstream appfile("file2",ofstream::app);
注意:模式是文件的属性而不是流的属性
下面是打开模式的有效组合
文件模式的组合
out 打开文件做写操作,删除文件中已存在的数据
out | app 打开文件做写操作,在文件尾写入
out | trunc  与out模式相同
in 读操作
in | out 打开文件做读写操作,并定位于文件开头处
in | out | trunc 打开文件做读写操作,删除文件中已经存在的数据
下面是一个打开并检查输入文件的程序
ifstream& open_file(ifstream &in, const string &file)
{
     in.close();
     in.clear();
     in.open(file.c_str());
     return in;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值