260 likes | 399 Views
第 11 章 流类库与输入/输出. 目录. I/O 流的概念 输出流 输入流 输入 / 输出流. I/O 流的概念. 当程序与外界环境进行信息交换时,存在着两个对象,一个是 程序中的对象 ,另一个是 文件对象 。 流是一种抽象,它负责在数据的 生产者 和数据的 消费者 之间建立联系,并管理数据的流动。 程序建立一个 流对象 ,并指定这个流对象与某个文件对象建立连接,程序操作流对象,流对象通过文件系统对所连接的文件对象产生作用。 读操作在流数据抽象中被称为(从流中) 提取 ,写操作被称为(向流中) 插入 。
E N D
目录 • I/O流的概念 • 输出流 • 输入流 • 输入/输出流
I/O流的概念 • 当程序与外界环境进行信息交换时,存在着两个对象,一个是程序中的对象,另一个是文件对象。 • 流是一种抽象,它负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动。 • 程序建立一个流对象,并指定这个流对象与某个文件对象建立连接,程序操作流对象,流对象通过文件系统对所连接的文件对象产生作用。 • 读操作在流数据抽象中被称为(从流中)提取,写操作被称为(向流中)插入。 • 输出流:ostream、ofstream、ostringstream • 输入流:istream、ifstream、istringstream
输出流对象 • 预先定义的输出流对象: • cout标准输出 • cerr标准错误输出,没有缓冲,发送给它的内容立即被输出。 • clog 类似于cerr,但是有缓冲,缓冲区满时被输出。 • ofstream类支持磁盘文件输出 • 如果在构造函数中指定一个文件名,当构造这个文件时该文件是自动打开的 • ofstreammyFile("filename",iosmode); • 可以在调用默认构造函数之后使用open成员函数打开文件 • ofstreammyFile; //声明一个静态输出文件流对象 • myFile.open("filename",iosmode); //打开文件,使流对象与文件建立联系 • ofstream* pmyFile = new ofstream; //建立一个动态的输出文件流对象 • pmyFile->open("filename",iosmode); • //打开文件,使流对象与文件建立联系
运算符 • 插入(<<)运算符是所有标准C++数据类型预先设计的,用于传送字节到一个输出流对象。 • 提取运算符(>>)对于所有标准C++数据类型都是预先设计好的,它是从一个输入流对象获取字节最容易的方法。
RMB例子 • class RMB • { • public: • RMB(unsigned int d=0,unsigned int c=0); • RMB operator +(RMB&); • RMB& operator ++(); • RMB operator ++(int); • friend ostream& operator << (ostream &os,const RMB &r); • friend istream& operator >> (istream &is, RMB &r); • private: • unsigned intyuan; • unsigned intjf; • };
ostream & operator << (ostream & os,const RMB &r) • { • os <<r.yuan<<' '<<r.jf<<endl; • return os; • } • istream& operator >> (istream & is, RMB &r) • { • is >>r.yuan>>r.jf; • return is; • } • int main(){ • RMB d4,d5; • cout<<"please input:yuanjf"<<endl; • cin>>d4>>d5; • cout<<d4<<d5<<endl; • }
控制输出格式 • 控制输出宽度 • 为了调整输出,可以通过在流中放入setw操纵符或调用width成员函数为每个项指定输出宽度。 • 例11-1 使用width控制输出宽度 #include <iostream> using namesoace std; int main() { double values[] = {1.23,35.36,653.7,4358.24}; for(inti=0;i<4;i++) { cout.width(10); cout << values[i] <<'\n'; } } 输出结果: 1.23 35.36 653.7 4358.24
例:使用*填充 • #include <iostream> • using namespace std; • int main() • { double values[]={1.23,35.36,653.7,4358.24}; • for(inti=0; i<4; i++) • { cout.width(10); • cout.fill('*'); • cout<<values[i]<<'\n'; • } • } 输出结果: ******1.23 *****35.36 *****653.7 ***4358.24
例11-2使用setw指定宽度 • #include <iostream> • #include <iomanip> • using namespace std; • int main() { • double values[]={1.23,35.36,653.7,4358.24}; • char *names[]={"Zoot","Jimmy","Al","Stan"}; • for(inti=0;i<4;i++) • cout<<setw(6)<<names[i] • <<setw(10)<<values[i] • <<endl; • } 输出结果: Zoot 1.23 Jimmy 35.36 Al 653.7 Stan 4358.24
例11-3设置对齐方式 • #include <iostream> • #include <iomanip> • using namespace std; • int main() • { double values[]={1.23,35.36,653.7,4358.24}; • char *names[]={"Zoot","Jimmy","Al","Stan"}; • for(inti=0;i<4;i++) • cout<<setiosflags(ios::left) • <<setw(6)<<names[i] • <<resetiosflags(ios::left) • <<setw(10)<<values[i] • <<endl; • } 输出结果: Zoot 1.23 Jimmy 35.36 Al 653.7 Stan 4358.24
例11-4控制输出精度 • #include <iostream> • #include <iomanip> • using namespace std; • int main() • { double values[]={1.23,35.36,653.7,4358.24}; • char *names[]={"Zoot","Jimmy","Al","Stan"}; • cout<<setiosflags(ios::scientific); • for(inti=0;i<4;i++) • cout<<setiosflags(ios::left) • <<setw(6)<<names[i] • <<resetiosflags(ios::left) • <<setw(10)<<setprecision(1) • << values[i]<<endl; • } 输出结果: Zoot 1 Jimmy 4e+001 Al 7e+002 Stan 4e+003
进制 • dec、oct和hex操纵符设置输入和输出的默认进制。
输出文件流成员函数 • 输出流成员函数有三种类型: • 与操纵符等价的成员函数。 • 执行非格式化写操作的成员函数。 • 其它修改流状态且不同于操纵符或插入运算符的成员函数。 • open函数 • 把流与一个特定的磁盘文件关联起来, 需要指定打开模式。 • put函数 • 把一个字符写到输出流中。 • write函数 • 把内存中的一块内容写到一个输出文件流中 • seekp和tellp函数 • 操作文件流的内部指针 • close函数 • 关闭与一个输出文件流关联的磁盘文件 • 错误处理函数 : 在写到一个流时进行错误处理
文件打开模式 • ios::out 以写入方式打开 • ios::out|ios::binary 以二进制写入方式打开 • ios::out|ios:trunc覆盖已有文件 • ios::out|ios:app追加文件 • ios::in 以读取方式打开 • ios::in|ios::binary 以二进制读取方式打开
使用流运算符输出文本文件 • #include <iostream> • #include <fstream> • using namespace std; • int main() • { ofstreamofile("test"); //以文本输出方式打开 • if(!ofile) • {cout<< "Cannot open file.\n"; return 1;} • ofile << 10 << " " << 123.23 << "\n"; //输出到文件 • ofile << "This program is designed by zrf and ssh!."; • ofile.close(); //关闭文件 • return 0; • }
例11-5向文件输出 • #include <fstream> • using namespace std; • struct Date • { intmo,da,yr; }; • int main() • { • Date dt = {6,10,92}; • ofstreamtfile("date.dat", ios::binary); • tfile.write((char *) &dt,sizeof(dt); • tfile.close(); • }
二进制输出文件 • 以通常方式构造一个流,然后使用setmode成员函数,在文件打开后改变模式。 • 使用ofstream构造函数中的模式参量指定二进制输出模式 • 使用二进制操作符代替setmode成员函数:ofs << binary;
输入流对象 • 如果在构造函数中指定一个文件名,在构造该对象时该文件便自动打开。 ifstreammyFile("filename",iosmode); • 在调用默认构造函数之后使用open函数来打开文件。 ifstreammyFile;//建立一个文件流对象 myFile.open(“filename”,iosmode); //打开文件“filename”
提取运算符(>>) • 提取运算符(>>)对于所有标准C++数据类型都预先设计好的。 • 是从一个输入流对象获取字节最容易的方法。 • ios类中的很多操纵符都可以应用于输入流。但是只有少数几个对输入流对象具有实际影响,其中最重要的是进制操纵符dec、oct和hex。
输入流成员函数 • open函数把该流与一个特定磁盘文件相关联。 • get函数的功能与提取运算符(>>)很相像,主要的不同点是get函数在读入数据时包括空白字符。(第6章介绍过) • getline的功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从读取的内容中删除终止字符。(第6章介绍过) • read成员函数从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数。如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取。 • seekg函数用来设置输入文件流中读取数据位置的指针。 • tellg函数返回当前文件读指针的位置。 • close函数关闭与一个输入文件流关联的磁盘文件。
使用流运算符读入文本文件 • #include <iostream> • #include <fstream> • using namespace std; • int main() • { char ch; inti; float f; char str[80]; • ifstreamifile("test"); //以文本输出方式打开文件 • if(!ifile) { • cout<< "Cannot open file.\n"; • return 1; • } • ifile >> i >> f >> ch >> str; //读文件 • cout << i << " " << f << " " << ch << "\n" << str; • ifile.close(); //关闭文件 • return 0; • }
课堂练习 • 对一个文件写入字符串“Jack”,整数60及其八进制的形式,再打开文件将他们读出来。
例11-9 设置位置指针 • #include <iostream> • #include <fstream> • using namespace std; • int main() • { char ch; • ifstreamtfile("payroll",ios::binary|ios::nocreate); • if(tfile) { • tfile.seekg(8); • while(tfile.good()) { • tfile.get(ch); • if (!ch) break; cout<<ch; } • } • else • { cout<<"ERROR: Cannot open file 'payroll'."<<endl; } • tfile.close(); • }
使用read()和write()函数读写二进制文件 • 例11-9
小结与复习建议 • 主要内容 • I/O流的概念、输出流、输入流、输入/输出流。 • 达到的目标 • 理解I/O流的概念,学会使用I/O流类库实现文件输入/输出及格式控制。