您的位置:首页 > 编程语言 > C语言/C++

C++文件输入和输出

2016-06-13 13:55 441 查看
1.引入头文件fstream
fstream头文件定义了用于文件输入的类ifstream和文件输出的类ofstream

2.写文件
1)创建一个ofstream对象来管理输出流
2)将该对象与文件关联起来
3)使用cout方式使用该对象,唯一区别是输出将进入文件,而不是屏幕。
4)关闭到文件的连接
示例如下:

ofstream fout;
fout.open("test.txt");
fout<<"write something";
fout.close();


创建对象和关联文件可使用构造函数合并到一步,以上代码等价于:

ofstream fout("test.txt");
fout<<"write something";
fout.close();


3.读文件
1)创建一个ifstream对象来管理输入流
2)将该对象与文件关联起来
3)使用ifstream的方法读文件
4)关闭到文件的连接
示例如下:

ifstream fin("test.txt");
char ch;
fin>>ch;//从文件中读取一个字符
char buf[80];
fin>>buf;//从文件中读取一个单词
fin.getline(buf,80);//从文件中读取一行
string line;
getline(fin,line);//读取一行转换成字符串
fin.close();


4.读写缓冲区
fstream流管理对象在使用cout或cin方式,读或写时,是通过缓冲区和文件进行交互的,
而不是逐字节读取或写入文件的。

关于close()函数,当流对象过期(如程序终止)时,到文件的连接自动关闭,
也可使用cose()显示关闭该连接。连接关闭后,将刷新缓冲区。

与文件的连接关闭后,并不会删除流,fstream流对象和它管理的缓冲区仍然存在,
可以将流重新连接到文件。

5.一个简单的读写文件示例

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
const string filename="test.txt";
int main()
{
ofstream fout(filename.c_str());
if(!fout.is_open())
{
cerr<<"无法打开文件 "<<filename<<endl;
exit(0);
}
cout<<"输入密码:";
float secret;
cin>>secret;
fout<<secret<<endl;
fout.close();

ifstream fin(filename.c_str());
if(!fin.is_open())
{
cerr<<"无法打开文件 "<<filename<<endl;
exit(0);
}
cout<<"输入的密码为:\n";
char ch;
while(fin.get(ch))
cout<<ch;
fin.close();
return 0;
}


程序中is_open()函数,是用来检查文件是否被打开
流对象的状态包括:
一切顺利,已达到文件尾,I/O操作失败等。如果一切顺利,流状态设置为0,否则设置为1。

6.打开多个文件
1)需要同时打开多个文件,则需要为每个文件创建一个流。
2)需要依次打开一组文件,可以只打开一个流,将它依次关联到各个文件。

如下例所示:

ifstream fin;
fin.open("test.txt");
fin.close();
fin.clear();
fin.open("test2.txt");
fin.close();


7.文件模式

常量含义
ios_base::in打开文件,以便读取
ios_base::out打开文件,以便写入
ios_base::ate打开文件,并移到文件尾,和ios_base::app的区别是,后者只能在文件尾写入,前者只是将写入指针初始化在文件尾
ios_base::app追加到文件尾
ios_base::trunc如果文件存在,则清空文件内容
ios_base::binary二进制文件
对于ifstream open(),默认的模式为ios_base::in
对于ofstream open(),默认的模式为ios_base::out|ios_base::trunc,打开并清空文件

8.二进制模式 ios_base::binary

文件的存储类型有两种,文本格式或二进制格式。
文本格式便于读取,而二进制格式更加精确,占用空间小,读取速度快。
写操作:

fout.write((char*)&T,sizeof T);


读操作:

fin.read((char*)&T,sizeof T);


注意需要将类型实例地址,强制转换为char*类型。

9.随机存取

随机存取是指,读写指针直接移动到文件的任何位置。

跳转函数:

istream & seekg(streamoff,ios_base::seekdir);//相对地址
istream & seekg(streampos);//绝对地址


第一个方法的意思是,离seekdir参数指定文件位置,距离streamoff的位置。
其中,streamoff单位的是字节,seekdir表示文件的三个位置(顶端ios_base::beg,底端ios_base::end,当前位置ios_base::cur)

第二个方法的意思是,离文件开头streampos的位置
streampos表示文件中的绝对位置,单位是字节

seekg()
移到文件开头

tellg()
返回读写指针当前的位置

下面,我们用二进制文件模式,写一个简单的随机存取示例:

#include<iostream>
#include<fstream>
#include<iomanip>
const int LIM=20;
struct planet
{
char name[LIM];
double population;
double g;
};
const char *file = "planets.dat";
inline void eatline(){while(std::cin.get()!='\n') continue;}
int main()
{
using namespace std;
planet pl;
cout<<fixed;

fstream finout;
finout.open(file,ios_base::in|ios_base::out|ios_base::binary);
int ct = 0;
if(finout.is_open())
{
finout.seekg(0);
cout<<"contents of file "<<file<<endl;
while(finout.read((char *)&pl,sizeof pl))
{
cout<<ct++<<":"<<setw(20)<<pl.name<<":"
<<setprecision(0)<<setw(12)<<pl.population
<<setprecision(2)<<setw(6)<<pl.g<<endl;
}
if(finout.eof())
finout.clear();
else{
cerr<<"无法打开文件 "<<file<<endl;
exit(0);
}
}
else{
cerr<<"无法打开文件 "<<file<<endl;
exit(0);
}
cout<<"enter record number to change:";
long rec;
cin>>rec;
eatline();
if(rec<0||rec>=ct)
{
cerr<<"无效 index number"<<endl;
exit(0);
}
streampos place = rec*sizeof pl;
finout.seekg(place);
if(finout.fail())
{
cerr<<"无法找到 index number"<<endl;
exit(0);
}
finout.read((char *)&pl,sizeof pl);
cout<<"找到的 index number"<<endl;
cout<<rec<<":"<<setw(20)<<pl.name<<":"
<<setprecision(0)<<setw(12)<<pl.population
<<setprecision(2)<<setw(6)<<pl.g<<endl;
if(finout.eof())
finout.clear();
cout<<"输入name:";
cin.get(pl.name,LIM);
eatline();
cout<<"population:";
cin>>pl.population;
cout<<"g:";
cin>>pl.g;
finout.seekp(place);
finout.write((char*)&pl,sizeof pl)<<flush;
if(finout.fail())
{
cerr<<"写失败 index number"<<endl;
exit(0);
}

ct = 0;
finout.seekg(0);
cout<<"contents of file "<<file<<endl;
while(finout.read((char *)&pl,sizeof pl))
{
cout<<ct++<<":"<<setw(20)<<pl.name<<":"
<<setprecision(0)<<setw(12)<<pl.population
<<setprecision(2)<<setw(6)<<pl.g<<endl;
}
finout.close();
cout<<"Done.\n";
return 0;
}


程序中,我们使用了一个特别的流管理对象fstream,
fstream继承子iostream,而iostream继承自istream和ostream
因此fstream继承了两个缓冲区,一个用于输入,一个用于输出
并能同步化两个缓冲区的处理。即输入指针和输出指针的位置始终相同。
这样用一个流管理对象,就可以同时进行读和写。

参考资料:《C++ Primer.Plus》 pp.768-788
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: