C++文件操作详解
2020-08-31
来源:步旅网
C++文件操作详解C++通过以下几个类支持文件的输入输出:ofstream:写操作(输出)的文件类(由ostream引申而来)ifstream:读操作(输入)的文件类(由istream引申而来)fstream:可同时读写操作的文件类(由iostream引申而来)打开文件(Openafile)对这些类的一个对象所做的第一个操作通常就是将它和一个真正的文件联系起来,也就是说打开一个文件。被打开的文件在程序中由一个流对象(streamobject)来表示(这些类的一个实例),而对这个流对象所做的任何输入输出操作实际就是对该文件所做的操作。要通过一个流对象打开一个文件,我们使用它的成员函数open():voidopen(constchar*filename,openmodemode);这里filename是一个字符串,代表要打开的文件名,mode是以下标志符的一个组合:ios::inios::outios::ateios::app为输入(读)而打开文件为输出(写)而打开文件初始位置:文件尾所有输出附加在文件末尾ios::trunc如果文件已存在则先删除该文件ios::binary二进制方式这些标识符可以被组合使用,中间以”或”操作符(|)间隔。例如,如果我们想要以二进制方式打开文件\"example.bin\"来写入一些数据,我们可以通过以下方式调用成员函数open()来实现:ofstreamfile;file.open(\"example.bin\ios::out|ios::app|ios::binary);ofstream,ifstream和fstream所有这些类的成员函数open都包含了一个默认打开文件的方式,这三个类的默认方式各不相同:类ofstream参数的默认方式ios::out|ios::truncifstreamios::infstreamios::in|ios::out只有当函数被调用时没有声明方式参数的情况下,默认值才会被采用。如果函数被调用时声明了任何参数,默认值将被完全改写,而不会与调用参数组合。由于对类ofstream,ifstream和fstream的对象所进行的第一个操作通常都是打开文件,这些类都有一个构造函数可以直接调用open函数,并拥有同样的参数。这样,我们就可以通过以下方式进行与上面同样的定义对象和打开文件的操作:ofstreamfile(\"example.bin\ios::out|ios::app|ios::binary);两种打开文件的方式都是正确的。你可以通过调用成员函数is_open()来检查一个文件是否已经被顺利的打开了:boolis_open();它返回一个布尔(bool)值,为真(true)代表文件已经被顺利打开,假(false)则相反。关闭文件(Closingafile)当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件需要调用成员函数close(),它负责将缓存中的数据排放出来并关闭文件。它的格式很简单:voidclose();这个函数一旦被调用,原先的流对象(streamobject)就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程(process)所有访问了。为防止流对象被销毁时还联系着打开的文件,析构函数(destructor)将会自动调用关闭函数close。文本文件(Textmodefiles)类ofstream,ifstream和fstream是分别从ostream,istream和iostream中引申而来的。这就是为什么fstream的对象可以使用其父类的成员来访问数据。一般来说,我们将使用这些类与同控制台(console)交互同样的成员函数(cin和cout)来进行输入输出。如下面的例题所示,我们使用重载的插入操作符<<:#include
intmain(){ofstreamexamplefile(\"example.txt\");if(examplefile.is_open())fileexample.txtThisisaline.Thisisanotherline.{examplefile<<\"Thisisaline.\\n\";examplefile<<\"Thisisanotherline.\\n\";examplefile.close();}return0;}从文件中读入数据也可以用与cin的使用同样的方法:Thisisaline.Thisisanotherline.//readingatextfile#include#include#includeintmain(){charbuffer[256];ifstreamexamplefil(\"example.txt\");if(!examplefile.is_open()){cout<<\"Erroropeningfile\";exit(1);}while(!examplefile.eof()){examplefile.getline(buffer,100);cout<#includeconstchar*filename=\"example.txt\";intmain(){longl,m;ifstreamfile(filename,ios::in|ios::binary);l=file.tellg();file.seekg(0,ios::end);m=file.tellg();file.close();cout<<\"sizeof\"<>,以及函数(如getline)来操作符输入和输出数据,没有什么实际意义,虽然它们是符合语法的。文件流包括两个为顺序读写数据特殊设计的成员函数:write和read。第一个函数(write)是ostream的一个成员函数,都是被ofstream所继承。而read是istream的一个成员函数,被ifstream所继承。类fstream的对象同时拥有这两个函数。它们的原型是:write(char*buffer,streamsizesize);read(char*buffer,streamsizesize);这里buffer是一块内存的地址,用来存储或读出数据。参数size是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。Thecompletefileisinabuffer//readingbinaryfile#include#includeconstchar*filename=\"example.txt\";intmain(){char*buffer;longsize;ifstreamfile(filename,ios::in|ios::binary|ios::ate);size=file.tellg();file.seekg(0,ios::beg);buffer=newchar[size];file.read(buffer,size);file.close();cout<<\"thecompletefileisinabuffer\";delete[]buffer;return0;}缓存和同步(BuffersandSynchronization)当我们对文件流进行操作的时候,它们与一个streambuf类型的缓存(buffer)联系在一起。这个缓存(buffer)实际是一块内存空间,作为流(stream)和物理文件的媒介。例如,对于一个输出流,每次成员函数put(写一个单个字符)被调用,这个字符不是直接被写入该输出流所对应的物理文件中的,而是首先被插入到该流的缓存(buffer)中。当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。这个过程称为同步(synchronization),它会在以下任一情况下发生:当文件被关闭时:在文件被关闭之前,所有还没有被完全写出或读取的缓存都将被同步。当缓存buffer满时:缓存Buffers有一定的空间限制。当缓存满时,它会被自动同步。控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flush和endl。明确调用函数sync():调用成员函数sync()(无参数)可以引发立即同步。这个函数返回一个int值,等于-1表示流没有联系的缓存或操作失败。在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:1、插入器(<<)向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<\"WriteStdout\"<<'n';就表示把字符串\"WriteStdout\"和换行字符('n')输出到标准输出流。2、析取器(>>)从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。在C++中,对文件的操作是通过stream的子类fstream(filestream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。一、打开文件在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:voidopen(constchar*filename,intmode,intaccess);参数:filename:要打开的文件名mode:要打开文件的方式access:打开文件的属性打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:ios::app:以追加的方式打开文件ios::ate:文件打开后定位到文件尾,ios:app就包含有此属性ios::binary:以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文ios::in:文件以输入方式打开ios::out:文件以输出方式打开ios::nocreate:不建立文件,所以文件不存在时打开失败ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败ios::trunc:如果文件存在,把文件长度设为0可以用“或”把以上属性连接起来,如ios::out|ios::binary打开文件的属性取值是:0:普通文件,打开访问1:只读文件2:隐含文件4:系统文件可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。例如:以二进制输入方式打开文件c:config.sysfstreamfile1;file1.open(\"c:config.sys\如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:file1.open(\"c:config.sys\");<=>file1.open(\"c:config.sys\0);另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:fstreamfile1(\"c:config.sys\");特别提出的是,fstream有两个子类:ifstream(inputfilestream)和ofstream(outpufilestream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。ifstreamfile2(\"c:pdos.def\");//以输入方式打开文件ofstreamfile3(\"c:x.123\");//以输出方式打开文件所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定义。二、关闭文件打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。三、读写文件读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式1、文本文件的读写文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:file2<<\"ILoveYou\";//向文件写入字符串\"ILoveYou\"inti;file1>>i;//从文件输入一个整数值。这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些操纵符功能输入/输出dec格式化为十进制数值数据输入和输出endl输出一个换行符并刷新此流输出ends输出一个空字符输出hex格式化为十六进制数值数据输入和输出oct格式化为八进制数值数据输入和输出setpxecision(intp)设置浮点数的精度位数输出比如要把123当作十六进制输出:file1<