C++文件操作


C++的输入输出流是IO系统向用户提供一个统一的接口,它隔离了具体的设备差异。输入输出流包括标准输入输出流和文件流。



标准输入输出流


我们在前面介绍基本的输入输出流那一章已经介绍过了,下面我们来简单回顾一下。


下图就是标准输入输出流的一个基本层次。基类是ios这个类,下面的输入流和输出流都是继承自ios类,iostream又派生自istream和ostream。我们在对数据进行输入输出的时候,系统会自动对数据类型进行转换,我们不需要自己去判断输入输出的类型。


file1.png


istream是输入流类,cin就是istream类型的对象;


ostream是输出流类,cout是ostream类型的对象。


在C++中允许用户重载运算符“<<”和“>>”,实现对象的输入和输出。重载这二个运算符时,在对象所在的类中,将重载这二个运算符的函数说明该类的友元函数。由于输入输出我们已经介绍过了,这里就只是回顾这么多。



文件流


文件流介绍

 

C++在头文件fstream.h中定义了C++的文件流类体系 ,当程序中使用文件时,要包含头文件fstream.h 。其中定义了各种文件操作运算符及函数。


下图是文件流的基本层次,可以看见和标准输入输出具有相同的结构。ifstream是输入流类,用来从文件中读取数据,ofstream是输出流类,用来向文件中写入数据。fstream继承自ifstream和ofstream,所以它同时具备读和写的能力。


file2.png


在涉及文本文件的操作时,将输入文件看成键盘,将输出文件看成显示器,格式不变。只需在程序中增加打开与关闭文件的语句。文件可以分为两大类:文本文件、二进制文件。



文件流使用


在对文件进行操作之前,我们首先定义一个文件类对象,只有将具体的文件类对象与具体的文件关联之后,我们才可以对这个文件进行各种操作。


1.定义文件对象


有以下三种类型的对象:


fstream file;//既可读又可写
ifstream infile;//可读不可写
ofstream outfile;//可写不可读


2.打开文件


ifstream infile;
infile.open(“C:\\myfile.txt"); //与这个文件建立关联
ofstream outfile;
outfile.open(“myoutfile.txt”);


3.读写文件


Std::string str;
Infile>>str; //从文件流中输入,可以看出和标准输入输出流的读取是一样的,使用流提取和流插入运算符,在这里是从infile所关联的文件中提取一个字符串存储到str中。
Outfile<<str; //将str所存储的字符写入到这个文件中


4.关闭文件


Infile.close();
Outfile.close();  //关闭后释放文件对象,取消与文件的关联。


定义fstream对象后,既可以对文件读又可以写。因此在open时需要给定打开的方式:


fstream  file1,file2;//定义了两个文件类的对象
file1.open(“file1.txt”,  ios::in);//用于输入,in和out为枚举值
pile2.open(“file2.txt”, ios::out);//用于输出

 

在open时常常会因为文件不存在,或正在被占用而打开失败。可以通过对文件对象进行判断来得知是否打开成功。


file1.open(“file.txt”, ios::in);
if(!file1)
{ 
  //文件打开失败。
}


有一个约定:


1)在打开文件进行读时,若文件不存在则打开失败;


2)写时,若文件不存在则新建一个文件。若存在则删除原来的文件的内容。



文本文件和二进制文件关于读写的区别


我们在上面介绍的打开文件和关闭文件这些方法对于文本文件和二进制文件都是一样的。但是在对文本文件和二进制文件写入的时候就有区别了。


1.文本文件与二进制文件读取方法不同


读写文本文件:


1)从文件读取一个字符:


file.getch(ch);


2)读取一行数据:


File.getline(str); //从文件读取时,当读取到文件尾时,函数返回值为0,可以据此来判断循环结束。


3)向文件写入一个字符:


file.put(ch);



实例,实现两个文本文件的拷贝


读写文本文件:


#include<iostream>
#include<fstream>
using namespace std;
 
int main()
{
ifstream infile;  //定义一个用来读取文件内容的对象
ofstream outfile;   //定义一个用来写入文件内容的对象
infile.open("D:\\test.txt");  //将对象与文件关联,以后该对象的操作就与该文件有关,指定了文件的路径
outfile.open("D:\\test_copy.txt");  //新写入文件的名字
if(!infile || !outfile)  //打开两个文件成功,如果有一个失败,就输出打开失败
{
cout<<"openfile failed!"<<endl;
return 0; //文件打开失败直接退出
}
char ch;
while(infile.get(ch))  //从test中读取字符,如果读取到文件的末尾或者读取失败,就返回false,退出循环
{
cout<<ch;  //输出这些字符
outfile.put(ch);  //将这些字符写入到test_copy中
}
 
infile.close();  //关闭对象与文件的关联,释放资源
outfile.close();
   return 0;
}


运行结果如下:可以看到test_copy文件中的确被写入了test的内容,而控制台也打印了这些内容。


file3.png


file4.png


读写二进制文件:


若在文件的open方法时没有特别说明,默认打开的是文本文件,


1)若要打开二进制文件,则要特别说明。


fstream   infile,outfile;
infile.open(“inf1.dat”,  ios::in| ios::binary);
outfile.open(“outf1.dat”,  ios::out| ios::binary);


ios::out和ios::in表示IO模式。枚举类型,多个枚举值可以使用运算符”|“组合使用。

  

2)二进制文件的关闭


关闭方法都一样,调用close方法。


3)二进制文件的读写


二进制文件的读写与文本文件不同,使用专门的方法。


infile.read( char *buff,   int nNum);  //buff存储数据的缓冲,nNum为要读取的长度,返回实际读取的数据长度。
infile.read(&Stuinfo, sizeof(Stuinfo)); //读取到的数据保存到Stuinfo中,将Stuinfo的长度也传入给它
infile.read(pBuff, 1024*sizeof(char));


4)向文件写入数据


outfile.write( pBuff, nLen );   //write返回实际写入的数据长度。


5)二进制文件的结束


infile.eof( ) ;  //当到达文件结束位置时,该函数返回一个非零值;否则返回零。



文件指针


1.打开文件之后,读取或写入一段数据之后,文件指针都会移动到读取或写入的数据的末尾。


file.read(pBuff, 1024); //读取1024个字节的数据,读取成功之后,文件指针向后偏移1024字节。
file.write(pBuff, 10); //写入十个字节的数据,写入成功之后,文件指针向后偏移10个字节。


2.读写方法可以自动的移动文件指针,除此之外还可以通过一个专门的函数随机的移动文件指针。


infile.seekg(nNum, ios::cur); // nNum为移动的字节数。
ios::cur表示从当前位置。还有另外两个相对位置ios::begin ,ios::end;
infile.seekg(10, ios::begin);//相对文件开始将文件指针移动10个字节。
infile.seekg(-20, ios::end);//相对文件结束,向前移动20字节


⒊实例,实现两个二进制文件的拷贝。


#include<iostream>
#include<fstream> //包含文件操作的头文件
using namespace std;
int main()
{
fstream infile;
fstream outfile;
infile.open("D:\\testb.dat", ios::in | ios::binary);  //打开一个二进制文件
outfile.open("D:\\testb_copy.dat", ios::out | ios::binary); //输出到一个二进制文件
if(!infile || !outfile)  //如果两个有一个操作失败,就返回打开失败
{
cout<<"openfile failed!"<<endl;
return 0;
}
 
char buff[1024];
while(!infile.eof())  //如果没有读取到文件的末尾,就继续读取
{
infile.read(buff, 1024);  //读取1024个字节到字符数组中
int nLen = infile.gcount();


为什么需要一个数而不是直接从buff中读取1024个字符写入到文件中呐?大多数情况下我们读写的文件都不会刚好是1024个倍数的字符,在最后一次读取的时候,就很可能不够1024个字符,那样你说写入的1024个字符就会是错误的,将错误的数据写入到文件中去了。所以我们使用gcount()获取每次buff实际读取到的字符,再将实际长度的字符写入到文件中就不会出错了。


outfile.write(buff, nLen);
}
infile.close(); //关闭文件的关联
outfile.close();
cout<<"copy sucess!"<<endl;
return 0;
}


运行结果如下:可以看见已经成功拷贝了这个文件


file5.png



【本文由麦子学院独家原创,转载请注明出处并保留原文链接】

logo
© 2012-2016 www.maiziedu.com
蜀ICP备13014270号-4 Version 5.0.0 release20160127

有一位课程导师想与你聊聊

客服热线 400-862-8862

回到顶部