1、第12章 流类体系与文件操作目的与要求12.1 流类体系12.2 文件操作本章小结目的与要求 通过本章学习,应理解I/O流、流类与流类体系的概念,掌握流的输入/输出控制格式。了解C+有关文件的概念及文件的使用方法,理解文件流类体系结构,掌握实现文件操作成员函数的使用方法,学会文本文件与二进制文件的打开、读/写、关闭等操作的编程方法。12.1 流类体系 12.1.1 流(Stream)1流类:用于完成输入/输出操作的类称为流类,所有流类的集合称为流类库。2流:用流类定义的对象称为流,如cin、cout等。3流的分类(1)文本流:由一串ASCII字符组成(2)二进制流:是由一串二进制数组成4缓冲流
2、与非缓冲流 系统在主存中开辟的用于临时存放输入/输出流信息的内存区称缓冲区 12.1.2 基本流类体系 基类iosstreambuf输入类istream输出类ostream输入/输出类iostream基本流类体系类ostream_withassign类istream_withassign当程序中使用输入/输出流时,要包含头文件iostream.h。12.1.3 标准输入输出流 1标准输入流cin(缓冲流)标准输入流cin通过重载“”运算符执行数据的输入操作,执行输入操作可看作为从流中提取一个字符序列。cin 为缓冲流。2标准输出流cout、clog(缓冲流)、cerr(非缓冲流)标准输出流co
3、ut、cerr、clog是通过重载“”运算符执行数据的输出操作,执行输出操作看作为向流中插入一个字符序列。cout、clog为缓冲流、cerr为非缓冲流。【例12.1】使用流cerr和clog实现数据的输出。例程例程3标准输出流默认设置(1)整数:十进制、域宽为0、右对齐、以空格填充。(2)实数:十进制、域宽为0、右对齐、以空格填充、精度6位小数、浮点输出。(3)字符串:域宽为0、右对齐、以空格填充。按实际字符串长度输出。12.1.4 流的格式控制 C+提供了格式控制成员函数与预定义格式控制函数供用户控制数据的输入/输出格式。(1)格式控制成员函数 ios类定义的格式控制成员函数的调用格式为:
4、(实参);(2)预定义格式控制函数 C+直接提供的预定义格式控制函数的调用格式为:(实参);1流的输出控制格式 使用流对象cout与插入运算符“”运算符来实现的。输入数据时,要注意数据间的分隔符、数据类型的一致和回车的使用。【例12.7】使用预定义格式控制符dec、oct、hex及输入流对象cin 输入十进制数、八进制数、十六进制数。例程例程12.1.5数据输入输出成员函数 1数据输入成员函数(1)字符输入成员函数:get()(2)字符串输入成员函数:getline()【例12.8】读取字符和字符串。2数据输出成员函数 字符输出成员函数:put()例程例程12.2 文件操作 12.2.1 C+
5、文件概述1文件(1)文件:由文件名标识的一组有序数据的集合称为文件。文件常放在磁盘上。(2)文件名:由字母数字序列组成。如:myfile.txt,youfile.txt。2文件的数据格式(1)二进制文件:由二进制数据组成(2)文本文件:由字符的ASCII码组成,最小存取单位为字符。3文件的使用方法 (1)打开文件;(2)对文件进行读/写操作;(3)关闭文件。12.2.2 C+的文件流类体系 基类iosstreambuf输入类istream输出类ostream输入/输出类iostream C+预定义的文件流类体系filebuf输出文件类ofstream输入文件类ifstream输入/输出文件类f
6、stream当程序中使用文件时,要包含头文件fstream.h。12.2.3 文件的使用方法 1定义文件流对象(1)读文件流对象定义格式:ifstream;例如:ifstream infile;/infile为读文件流对象(2)写文件流对象定义格式:ofstream;例如:ofstream outfile;/outfile为写文件流对象(3)读/写文件流对象定义格式:fstream;例如:fstream iofile;/iofile为读/写文件流对象 2打开文件(1)使用成员函数open()打开文件打开文件的格式为:文件流对象.open(“文件名”,ios:moda);文件打开方式:moda=
7、in、out、app、nocreate、noreplace、binary。例如:infile.open(myfile.txt,ios:in);或 infile.open(myfile.txt);outfile.open(youfile.txt,ios:out);或 outfile.open(youfile.txt);(2)定义文件流对象时通过构造函数打开文件在定义文件流对象时直接调用构造函数打开文件。例如:ifstream infile(myfile.txt,ios:in);或 ifstream infile(myfile.txt);ofstream outfile(“youfile.txt”
8、,ios:out);或 ofstream outfile(youfile.txt);(3)判断文件打开成功 无论是调用成员函数open()来打开文件,还是用构造函数来打开文件,在打开后,都要判断打开是否成功。若文件打开成功,则文件流对象值为非零值;若打开不成功,则其值为0。例如:按只读方式打开文件myfile.txt的一般过程为:ifstream infile(myfile.txt);if (!infile)cout不能打开的文件:myfile.txtendl;exit(1);判断文件打开成功或char filename256;coutfilename;ifstream infile;infi
9、le.open(filename);if(!infile)cout不能打开的文件:filename”或插入运算符“ch;/从输入流infile所关联的文件myfile.txt中 /提取一个字符赋于变量ch outfile”和插入运算符“”将源程序文件拷贝到目的文件中。例程例程例程例程文本文件的使用 【例12.11】用输入输出文件类fstream定义文件流对象,用文件流对象的成员函数打开文件。使用成员函数getline与插入运算符“”、插入运算符“”与插入运算符“ch)outfilech;用成员函数get()、getline()与put()对文件读写。例如:char ch,buff500;whi
10、le(infile.get(ch)outfile.put(ch);while(infile.getline(buff,500)outfilebuff;(4)关闭文件 用成员函数close关闭文件,例如:infile.close();outfile.close();关闭文件时,系统将与该文件相关联的内存缓冲区中的数据写到文件中,收回与该文件相关的主存空间,将文件名与文件对象之间建立的关联断开。5二进制文件的使用 二进制文件的使用与文本文件的使用类似,首先要定义文件流对象,然后用open函数打开文件,打开方式必须使用ios:binary。读/写文件时要使用读函数read()与写函数write(),
11、并可用定位函数seekg与seekp移动文件指针,随机读/写文件中任一字节单元的内容。文件使用完毕后,要用close函数关闭文件。例12.1#include void main(void)cerra;clog”a*a=”a*aendl;返回返回例12.2#include void main()float a=11,22.2,33.33,44.444,55.5555;for(int i=0;i5;i+)cout.width(10);/设置输出域宽为10 coutain;返回返回例12.3#include#include void main(void)char*name=Zhou,Zhao,Liu
12、,Chen,Li;double score=11,22.2,33.33,44.444,55.5555;for(int i=0;i5;i+)coutsetw(6)nameisetw(10)scorein;返回返回例12.4#include#include void main(void)char*name=Zhou,Zhao,Liu,Chen,Li;double score=11,22.2,33.33,44.444,55.5555;for(int i=0;i5;i+)coutsetiosflags(ios:left)setw(6)namei/设置输出姓名左对齐、域宽为6 resetiosflags
13、(ios:left)/取消输出左对齐 setiosflags(ios:right|ios:scientific)/设置右对齐、科学记数法 setw(10)scorein;/设置输出域宽为10 返回返回例12.5#include#include void main(void)char*name=Zhou,Zhao,Liu,Chen,Li;double score=11,22.2,33.33,44.444,55.5555;for(int i=0;i5;i+)coutsetiosflags(ios:left)setw(6)namei resetiosflags(ios:left)setiosflag
14、s(ios:fixed)/先设置定点方式 setprecision(1)scorein;/再设置小数点后一位有效数字 返回返回例12.6#include#include main()int x=64;coutsetiosflags(ios:oct)xtresetiosflags(ios:oct)setiosflags(ios:hex)xtresetiosflags(ios:hex)setiosflags(ios:dec)xendl;coutoctxthexxtdecxendl;返回返回例12.7#include void main(void)int a,b,c;coutdeca;coutoct
15、b;couthexc;couta=decaendl;coutb=decbendl;coutc=deccendl;返回返回例12.8(1)#include void main(void)char c1,c2,c3;char str180,str2100;cout输入三个字符:;c1=cin.get();cin.get(c2);cin.get(c3);cin.get();/A cout输入第一行字符串:;cin.get(str1,80);cin.get();/B例12.8(2)cout输入第二行字符串:;cin.getline(str2,100);coutc1=c1endl;coutc2=c2en
16、dl;coutc3=c3endl;coutstr1=str1endl;coutstr2=str2endl;返回返回例12.9(1)#include#include#include void main(void)char fname1256,fname2256;coutfname1;coutfname2;ifstream infile;infile.open(fname1);ofstream outfile;outfile.open(fname2);例12.9(2)if(!infile)cout不能打开输入文件:fname1endl;exit(1);if(!outfile)cout不能打开目的文
17、件:fname2endl;exit(1);infile.unsetf(ios:skipws);/设置为不要跳过文件中的空格。char ch;while(infile.get(ch)/从源文件中提取一个字符到变量ch中;outfile.put(ch);/将ch中的字符写入目的文件中。infile.close();/关闭源文件 outfile.close();/关闭目的文件返回返回例12.10(1)#include#include#include void main(void)char fname1256,fname2256;coutfname1;coutfname2;ifstream infil
18、e(fname1);/用构造函数打开源文件 ofstream outfile(fname2);/用构造函数打开目标文件 例12.10(2)if(!infile)cout”不能打开输入文件:”fname1endl;exit(1);if(!outfile)cout”不能打开目的文件:”fname2ch)/从源文件中提取一个字符到变量ch中;outfilech;/将ch中的字符写入目的文件中。infile.close();/关闭源文件 outfile.close();/关闭目的文件返回返回例12.11(1)#include#include#include void main(void)char fn
19、ame1256,fname2256;char buff300;coutfname1;coutfname2;fstream infile,outfile;infile.open(fname1,ios:in|ios:nocreate);outfile.open(fname2,ios:out|ios:noreplace);例12.11(2)if(!infile)cout源文件不存在,不能打开源文件!endl;exit(1);if(!outfile)cout目标文件已存在,不能新建目标文件!endl;exit(2);while(infile.getline(buff,300)/从源文件中读一行字符到缓
20、冲区;outfilebuffn;/将缓冲区中一行字符写入目的文件中。infile.close();/关闭源文件 outfile.close();/关闭目的文件 返回返回例12.12(1)#include#include#include void main(void)float a33;int i,j;char fname256;coutfname;ofstream outfile;outfile.open(fname);例12.12(2)if(!outfile)cout不能打开目的文件:fname;exit(1);cout输入数组元素:endl;for(i=0;i3;i+)for(j=0;ja
21、ij;for(i=0;i3;i+)for(j=0;j3;j+)outfilesetw(10)aij;outfilen;outfile.close();返回返回例12.13(1)#include#include#include void main(void)float a33;int i,j;char fname256;coutfname;ifstream infile;infile.open(fname,ios:in|ios:nocreate);例12.13(2)if(!infile)cout不能打开输入文件fname;exit(1);for(i=0;i3;i+)for(j=0;jaij;/从
22、文本文件中提取数据到二维数组元素中 float max=a00;for(i=0;i3;i+)for(j=0;jmax)max=aij;/求出二维数组元素的最大值例12.13(3)cout二维数组的元素值:endl;for(i=0;i3;i+)for(j=0;j3;j+)coutsetw(10)aij;/输出二维数组的元素值 coutendl;coutmax=maxendl;/输出二维数组的最大值 infile.close();返回返回例12.14(1)#include#include void main(void)float a33;int i,j;char fname256;coutfnam
23、e;ofstream outfile;outfile.open(fname,ios:out|ios:binary);if(!outfile)cout不能打开目的文件:fname;exit(1);例12.14(2)cout输入数组元素:;for(i=0;i3;i+)for(j=0;jaij;for(i=0;i3;i+)for(j=0;j3;j+)outfile.write(char*)&aij,sizeof(float);outfile.close();返回返回例12.15(1)#include#include void main(void)float a33;int i,j;char fnam
24、e256;coutfname;ifstream infile;infile.open(fname,ios:in|ios:binary);例12.15(2)if(!infile)cout不能打开输入文件fname;exit(1);for(i=0;i3;i+)for(j=0;j3;j+)infile.read(char*)&aij,sizeof(float);float max=a00;for(i=0;i3;i+)for(j=0;jmax)max=aij;例12.15(3)for(i=0;i3;i+)for(j=0;j3;j+)couttaij;coutendl;coutmax=maxendl;i
25、nfile.close();返回返回例12.16(1)#include#include#include#include void main(void)/以只写方式打开二进制文件SIN.BIN fstream outfile(SIN.BIN,ios:out|ios:binary);int i;if(!outfile)cout不能打开输出文件SIN.BIN n;exit(1);例12.16(2)double s91;for(i=0;i=90;i+)si=sin(i*3.1415926/180);outfile.write(char*)s,sizeof(double)*91);/一次写入91个实数
26、/以只读方式打开二进制文件SIN.BIN fstream infile(SIN.BIN,ios:in|ios:binary);if(!infile)cout不能打开输入文件SIN.BIN n;exit(1);例12.16(3)infile.read(char*)s,sizeof(double)*91);/一次读出91个实数 for(i=0;i=90;i+)coutsetw(10)sit;if(i+1)%5=0)coutendl;infile.close();outfile.close();返回返回例12.17(1)#include#include void main(void)char fna
27、me1256,fname2256;char buff4096;/建立4K缓冲区 coutfname1;coutfname2;例12.17(2)fstream infile,outfile;infile.open(fname1,ios:in|ios:binary);outfile.open(fname2,ios:out|ios:binary);if(!infile)cout不能打开输入文件:fname1endl;exit(1);if(!outfile)cout不能打开目的文件:fname2endl;exit(2);例12.17(3)int n;while(!infile.eof()/文件不结束就
28、继续循环;infile.read(buff,4096);/一次读4096个字节 n=infile.gcount();/取实际读的字节数 outfile.write(buff,n);/按实际读的字节数写入文件 infile.close();/关闭源文件 outfile.close();/关闭目的文件 返回返回例12.18(1)#include#include#include void main(void)char c1,c2,c=ABCDEFGH;/用构造函数打开二进制文件letter.dat ofstream outfile(letter.dat,ios:out|ios:binary);if(
29、!outfile)cout不能打开目的文件:;exit(1);例12.18(2)outfile.write(c,sizeof(char)*(strlen(c)+1);/将字符串c写入letter.dat文件缓冲区 outfile.flush();/将缓冲区中字符串写入磁盘文件中。/用构造函数打开二进制文件letter.dat ifstream infile(letter.dat,ios:in|ios:binary);if(!infile)cout不能打开源文件;exit(1);infile.seekg(3);/将指针移到第3个字节处 infile.read(char*)&c1,sizeof(c
30、har);/将文件第3个字节处字母读入c1 coutc1n;/显示c1的内容 例12.18(3)coutc1;outfile.seekp(5);/将输出文件指针定位在第5个字节处 outfile.write(char*)&c1,sizeof(char);/将新字母写入第5个字节单元 outfile.flush();/刷新缓冲区 infile.seekg(5);/将输入文件指针定位在第5个字节处 infile.read(char*)&c2,sizeof(char);/将输入文件第5个字节内容读入c2 coutc2n;/显示c2中内容 outfile.close;infile.close();返回
31、返回例12.19(1)#include#include#include void main(void)char c1,c2,c=ABCDEFGHIJ;/用构造函数打开二进制文件letter.dat ofstream outfile(letter.dat,ios:out|ios:binary);if(!outfile)cout不能打开目的文件:;exit(1);例12.19(2)coutoutfile.tellp()endl;/显示输出文件流的当前文件指针值 /将字符串c写入letter.dat文件缓冲区 outfile.write(c,sizeof(char)*(strlen(c)+1);co
32、utoutfile.tellp()endl;/显示输出文件流的当前文件指针值 outfile.flush();/将缓冲区中字符串写入磁盘文件中。/用构造函数打开二进制文件letter.dat ifstream infile(letter.dat,ios:in|ios:binary);if(!infile)cout不能打开源文件;exit(1);例12.19(3)coutinfile.tellg()endl;/显示输入文件流的当前文件指针值 infile.seekg(3);/将指针移到第3个字节处 coutinfile.tellg()endl;/显示输入文件流的当前文件指针值 infile.se
33、ekg(3,ios:cur);/将指针后移3个字节到第6 个字节处 coutinfile.tellg()endl;/显示输入文件流的当前文件指针值 infile.seekg(-4,ios:cur);/将指针前移4个字节到第2个字节处 coutinfile.tellg()endl;/显示输入文件流的当前文件指针值 infile.seekg(-3,ios:end);/将指针从文件尾前移3个字节,到第8个字节处 coutinfile.tellg()endl;/显示输入文件流的当前文件指针值 outfile.close;infile.close();返回返回例12.20(1)#include#incl
34、ude void main(void)ofstream outfile(data.dat,ios:out|ios:binary);/A if(!outfile)cout不能打开输出文件data.dat n;exit(1);int i;for(i=5;i1000;i+=2)outfile.write(char*)&i,sizeof(int);outfile.close();例12.20(2)ifstream infile(data.dat,ios:in|ios:binary);if(!infile)cout不能打开输入文件data.dat n;exit(1);int x;infile.seekg(20*sizeof(int);for(i=0;i10;i+)infile.read(char*)&x,sizeof(int);coutxt;infile.close();返回返回