1第7章文件操作2本章内容•7.1文件的基本概念•7.2打开文件和关闭文件•7.3顺序访问文件•7.4随机访问文件•7.5输入输出文件综合举例采用流操作符读写采用函数成员读写流对象做参数出错检测多文件操作二进制文件37.1文件的基本概念•7.1.1输入输出的基本概念•7.1.2文件的基本概念和分类•7.1.3使用文件的基本过程•7.1.4文件流类型47.1.1输入输出的基本概念•数据在外部设备和内存之间的传递,我们称之为输入输出。外部设备内部程序数据输入/读/取输出/写/存数据外部设备•外部设备:键盘,显示器,打印机,外部存储器等。5外部设备•键盘:标准输入设备。操作符实现标准输入。•显示器:标准输出设备。操作符实现标准输出。•第1章已介绍标准输入输出设备的操作,本章介绍外部存储器上的输入输出操作,即文件的输入输出操作,因为外部存储器上的数据是以文件形式存储的。67.1.2文件的基本概念和分类•文件是存储在存储介质上的一组信息的集合,一般由操作系统管理。•作用:存储数据,便于处理或共享。•数据文件分为文本文件和二进制文件。–在文本文件中,存储的是字符编码。–在二进制文件中的数据是其内存映像,即数据在内存中的表示形式。7文本文件例•数值12345在ASCII文件中的存放形式0011000100110010001100110011010000110101'1''2''3''4''5'ASCII形式:(字符编码)8二进制文件例•数值12345在内存中int型数据的形式0011000000111001在二进制文件中的形式:0000000000000000001100000011100100000000000000009文本文件和二进制文件比较•整数12345–若存于文本文件中,占5个字节。即存放5个ASCII字符,其存储的是0和1组成的二进制值。–若存于二进制文件中,占4个字节(即内存映象)。因为一个整数在内存中占4个字节,其存储的仍是二进制值。•但是两种二进制形式的本质是不一样的。107.1.3使用文件的基本过程•使用文件分为三步.1.必须打开文件2.对文件进行读或者写操作3.文件操作结束时关闭文件•如何打开?•注意和标准输入输出类比117.1.4文件流类型•文件可看成是由字符(字节)组成的流•流式文件:由一个个字符(字节)数据顺序组成•C++的3种文件流类型(P162表7-1),定义在fstream.h中,所以在对文件进行操作之前,必须用include指令包含该头文件–ofstream输出文件流类型–ifstream输入文件流类型–fstream文件流类型12文件流对象•对文件的操作通过文件流对象实现,文件流对象通过文件流类型创建–ofstreamoutputFile;–ifstreaminputFile;–fstreamdataFile;137.2打开文件和关闭文件•7.2.1打开文件的两种方式•7.2.2测试文件打开是否成功•7.2.3关闭文件147.2.1打开文件的两种方式•使用流对象的open函数成员打开文件•定义时直接打开15ifstreaminputFile;inputFile.open(d:\\customer.dat);例1:文件名由字符串常量表示用open函数打开文件字符串中,两个反斜线表示一个反斜线ifstreaminputFile;charfileName[20];cinfileName;inputFile.open(fileName);例2:文件名是字符数组或string对象16用open函数打开文件fstreamdataFile;dataFile.open(info.dat,ios::out);例3:第2个参数——指定打开模式fstream类的open函数必须有两个参数,而对于ifstream和fstream流对象,都有缺省模式(P163表7-2)ofstream:文件存在,刷新;不存在,创建ifstream:文件存在,打开;不存在,失败17用open函数打开文件•通过指定打开模式改变缺省操作ofstreamoutput;output.open(values.dat,ios::noreplace);ios::app追加模式ios::ate如果已存在,直接转到文件尾部ios::binary二进制方式ios::in从文件中读数据ios::out向文件中写数据ios::nocreate如果文件不存在,则不会创建ios::noreplace如果文件存在,将失败ios::trunc如果文件存在,它的内容将会被删除(P164表7-3)18用open函数打开文件•各种模式可通过|符号连接使用fstreamdataFile;dataFile.open(info.dat,ios::in|ios::out);//dataFile.open(info.dat,ios::out|ios::app)19定义流对象时打开文件•例fstreamdataFile(names.dat,ios::in|ios::out);207.2.2测试文件打开是否成功•有时open函数会不起作用•对文件的操作必须先确保打开文件成功ifstreamdataFile;dataFile.open(cust.dat,ios::in);if(!dataFile){cout打开文件失败.\n;exit(0);}dataFile.fail()217.2.3关闭文件•缓冲的概念•文件的关闭22缓冲的概念•外部设备的操作速度与CPU的运行速度相比是非常缓慢的,若每输入输出一次,CPU都驱动一次外部设备,则程序执行效率很低。•引入缓冲的目的是解决CPU的运行速度和外部设备操作速度不匹配的矛盾。•以输出为例,程序中的每次输出都是先输出到缓冲区,当缓冲区被写满或缓冲区不满但程序干涉时,才将缓冲区中的数据成批送往外部设备,这样可减少对外部设备的驱动次数,提高输出速度。23缓冲文件系统外部设备内部程序数据输入输出数据外部设备内存缓冲区内存缓冲区设立缓冲区之后,因为CPU与内存的存取速度相差不大,所以以缓冲区为中介成批输入输出数据要比直接对外设输入输出数据节约时间。24文件的关闭•当程序不再使用文件时,应关闭文件,原因如下:–操作系统限制同时打开的文件数量–不关闭文件可能会丢失数据磁盘文件输出文件缓冲区输入文件缓冲区程序数据区a缓冲文件系统:close25文件的关闭•调用close函数成员关闭文件fstreamdataFile;dataFile.open(cust.dat,ios::in);if(!dataFile){cout打开文件失败.\n;exit(0);}……dataFile.close();267.3顺序访问文件•7.3.1采用流操作符读写文件•7.3.2采用函数成员读写文件•7.3.3流对象做参数△•7.3.4出错检测•7.3.5多文件操作•7.3.6二进制文件△277.3.1采用流操作符读写文件•采用写文件•格式化输出在写文件中的应用•采用从文件读数据•检测文件结束28采用写文件•【例7-3】使用向一个文件写入信息。#includeiostreamusingnamespacestd;#includefstream#includecstdlibvoidmain(){fstreamdataFile;dataFile.open(demofile.txt,ios::out);if(!dataFile){coutErroropeningfile.\n;exit(0);}dataFileJones\n;dataFileSmith\n;dataFile.close();dataFile.open(demofile.txt,ios::app);dataFileWillis\n;dataFileDavis\n;dataFile.close();}注意30格式化输出在写文件中的应用•对文件的格式化输出,与cout对显示器的格式化输出方法一样,从操作系统的角度讲,显示器也是文件•【例7-5】格式化输出在文件中的应用.#includeiostream.h#includefstream.h#includeiomanip.hvoidmain(){fstreamoutFile(table.txt,ios::out);doublenums[2][2]={2.89766,5.12,3.1234,7.65432};outFile.precision(4);for(introw=0;row2;row++){for(intcol=0;col2;col++)outFilesetw(10)nums[row][col];outFileendl;}outFile.close();}32采用从文件读数据•【例7-6】采用从文件读取数据.#includeiostreamusingnamespacestd;#includefstream#includecstdlibvoidmain(){fstreamdataFile;charname[81];dataFile.open(demofile.txt,ios::in);if(!dataFile){coutFileopenerror!endl;exit(0);}for(intcount=0;count4;count++){dataFilename;coutnameendl;}dataFile.close();}当不知道文件中有多少数据时?由读指针从文件取数据,并通过空白字符区分数据34检测文件结束•eof()成员函数报告文件结尾。•注意:“endoffile”意味着文件指针已经超出了最后一个数据的范围,无数据可读,此时,eof()返回一个非零值while(!inFile.eof())inFilevar;if(inFile.eof())inFile.close();voidmain(){……//openfilewhile(!dataFile.eof()){dataFilename;if(dataFile.fail())break;coutname;}dataFile.close();}•【例7-7】对例7-6的改进367.3.2采用函数成员读写文件•采用函数成员getline读文件•采用函数成员get和put读写文件37采用函数成员getline读文件•采用读文件的缺陷:空白字符是数据之间的分界符,采用操作符进行读取时,会略过空白字符。•getline函数成员:一次读取一行数据,包含空白字符dataFile.getline(str,81,'\n');str:数组名或字符指针,从文件中读取的数据将存储在该指针所指的空间中界符,缺省值,可选38#includeiostreamusingnamespacestd;#includefstream#includecstdlibvoidmain(){fstreamreadFile;charinput[81];readFile.open(murphy.txt,ios::in);if(readFile.fail()){cout打开文件失败!endl;exit(0);}【例7-11】采用getline函数成员从文件中一次读取一行。39//use'\n'asadelimiterwhile(!readFile.eof()){readFile.getline(input,81);if(readFile.fail())break;coutinputendl;}readFile.close();}40采用函数成员get和put读写文件•get成员函数:每次从文件读取一个字符。inFile.get(ch);•put成员函数:每次向文件写入一个字符。outFile.put(ch);•【例7-13】get和put的应用。41intmain(){fstr