C++文件操作
ofstream fout; 创建一个对象
fout.open("jar.txt"); 打开一个文件
ofstream fout("jar,txt"); 等价于上面两步操作
然后,以使用cout的方式使用fout(或其他名称)。例如 fout<<" Dull Data";
ostream是ofstream的基类,既可以使用任何格式控制。
ifstream fin;
fin.open("Test.txt");
ifstream fin("Test.txt"); 与上面两步操作等价
char ch;
fin>>ch; 读取一个字母
char buff[80];
cin>>buff; 读取一个word
fin.getline(buff,80); 从文件中读取一行
string line;
getline(fin,line); 从文件中读取一行
fout.close(); 显式的关闭文件
fin.close() 显式的关闭文件
控制台中可以用ctrl+z代替EOF
逐词读取 空格隔开
ifstream fin("data.txt");
string s;
while( fin >> s )
{
cout << "Read from file: " << s << endl;
}
逐行读取 回车换行隔开
方式一: //读取到string对象 不用指定长度
ifstream fin("data.txt");
string s;
while( getline(fin,s) )
{
cout << "Read from file: " << s << endl;
}
方式二: //读取到字符数组 指定长度
ifstream fin("data.txt");
const int LINE_LENGTH = 100;
char str[LINE_LENGTH];
while( fin.getline(str,LINE_LENGTH) )
{
cout << "Read from file: " << str << endl;
}
getline()函数详解
getline()的原型是istream& getline ( istream &is , string &str , char delim );
从一个流中读取一串字符放到指定位置,读取时遇到delim停止(默认为\n);
例程:
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main()
{
string filename;
cout << "Enter name for new file:";
cin >> filename;
ofstream fout(filename.c_str());
fout << "For your eyes only!\n";
cout << "Enter your secret number:";
float secret;
cin >> secret;
fout << "Your secret number is " << secret << endl;
fout.close();
ifstream fin(filename.c_str());
cout << "Here are the contents of " << filename << ":\n";
char ch;
while (fin.get(ch))
{
cout << ch;
}
cout << "Done!\n";
fin.close();
return 0;
}
检测文件是否成功打开。
fin.open(argv[file]);
if(fin.fail())
{
......
}
或者
if(!fin)
{
......
}
或者
if(!fin.is_open())
{
......
}
或者
if(!fin.good())
{
......
}
依次打开多个文件
ifstream fin;
fin.open("test.txt");
...
fin.close();
fin.clear();
fin.open("test.txt");
...
fin.close();
文件打开模式选择
#include<fstream>
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
const char* file = "guests.txt";
int main()
{
char ch;
ifstream fin;
fin.open(file);
if (fin.is_open())
{
cout << "Here are the current contents of the" << file << "fiel:\n";
while (fin.get(ch))
{
cout << ch;
}
fin.close();
}
ofstream fout(file, ios::out | ios::app);
if (!fout.is_open())
{
cerr << "Can't open" << file << "file for out put.\n";
exit(EXIT_FAILURE);
}
cout << "Enter guest names (enter a blank line to quit):\n";
string name;
while (getline(cin,name)&&name.size()>0)
{
fout << name << endl;
}
fout.close();
fin.clear();
fin.open(file);
if (fin.is_open())
{
cout << "Here are the new contents of the " << file << "file:\n";
while (fin.get(ch))
{
cout << ch;
}
fin.close();
}
cout << "Done!\n";
return 0;
}
文本形式和二进制形式保存
const int LIM = 20;
struct planet
{
char name[LIM];
double population;
double g;
}
planet pl;
保存方式一:
ofstream fout("planet.dat",ios_base::out|ios_base::app);
fout<<pl.name<<" "<<pl.population<<" "<<pl.g<<"\n";
保存方式二:
ofstream fout("planet.dat",ios_base::out|ios_base::app|ios_base::binary);
fout.write((char*)&pl,sizeof pl);
采用二进制文件模式时:速度快,不丢失数据,不发生隐含转换。
采用文本模式时:会发生隐式转换,可能丢失数据。在不同的系统上转换结果可能不一样。
采用write()函数的时候,第一个参数是地址,第二个参数是字节。地址必须转换为char*类型
read()和write()的功能是相反的,可以用read()来恢复write()写入的数据。
案例:
#include<iostream>
#include<fstream>
#include<iomanip>
#include<stdlib.h>
using namespace std;
inline void eatline() { while (std::cin.get() != '\n')continue; }
struct planet
{
char name[20];
double population;
double g;
};
const char* file = "planets.dat";
int main()
{
planet pl;
cout << fixed << right;
ifstream fin;
fin.open(file, ios_base::in | ios_base::binary);
if (fin.is_open())
{
cout << "Here are the current contents of the " << file << "file:\n";
while (fin.read((char*)&pl,sizeof pl))
{
cout << setw(20) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
}
fin.close();
}
ofstream fout(file, ios_base::out | ios_base::app | ios_base::binary);
if (!fout.is_open())
{
cerr << "Can't Open " << file << "fiel for output:\n";
exit(EXIT_FAILURE);
}
cout << "Enter plant name(Enter a blank line to quit):\n";
cin.get(pl.name, 20);
while (pl.name[0]!='\0')
{
eatline();
cout << "Enter planetary population:";
cin >> pl.population;
cout << "Enter planet's acceleration of gravity:";
cin >> pl.g;
eatline();
fout.write((char *)&pl, sizeof pl);
cout << "Enter planet name (Enter a blank line to quit):\n";
cin.get(pl.name, 20);
}
fout.close();
fin.clear();
fin.open(file, ios_base::in | ios_base::binary);
if (fin.is_open())
{
cout << "Here are the new contents of the " << file << "file:\n";
while (fin.read((char*)&pl,sizeof pl))
{
cout << setw(20) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
}
fin.close();
}
cout << "Done!\n";
}
打开文件用于读写:
fstream finout;
finout.Open(file,ios::in|ios::out|ios::binary);
打开文件,移动到文件开头并显示文件内容。
int ct=0;
if(finout.is_open())
{
finout,seekg(0);
cout<<"Here are the current contents of the "
<<file<<"file:\n";
while(finout.read((char*)&pl,sizeof pl))
{
cout<<ct++<<": "<<setw(LIM)<<pl.population
<<setprecision(0)<<setw(12)<<pl.population
<<setprecision(2)<<setw(6)<<pl.g<<endl:
}
if(finout.eof())
{
finout.clear();
}
else
{
cerr<<"Error in reading "<<file<<".\n";
exit(EXIT_FAILURE);
}
}
else
{
cerr<<file<<" could ont be opened---bye.\n";
exit(EXIT_FAILURE);
}
选择修改记录:
cout<<"Enter the record number you wish to change: ";
long rec;
cin>>rec;
eatline()
if(rec<0||rec>=ct)
{
cerr<<"Invalid record bumber --bye \n";
exit(EXIT_FAILURE);
}
streampos place=rec * sizeof pl;
finout.seekg(place);
ct 表示记录号。如果试图超过文件尾,程序将退出。
接下来显示当前记录:
finout.read((char *)&pl,sizeof pl);
cout<<"Your selection:\n";
cout<<rec<<": "<<setw(LIM)<<pl.name<<": "
<<setprecision(0)<<setw(12)<<pl.population
<<setprecision(2)<<setw(6)<<pl.g<<endl;
if(finout.eof())
{
finout.clear();
}
显示记录之后,现在可以执行修改记录。
cout<<"Enter planet name: ";
cin.get(pl.name,LIM);
eatline();
cout<<"Enter planetary population: ";
cin>>pl.population;
cout<<"Enter planet's acceleration of gravity: ";
cin>>pl.g;
finout.seekp(place);
finout.write((char*)&pl,sizeof pl)<<flush;
if(finout.fail())
{
cerr<<"Error on attempted write\n";
exit(EXIT_FAILURE);
}
总结案例:
#include<iostream>
#include<fstream>
#include<iomanip>
#include<stdlib.h>
using namespace std;
const int LIM = 20;
struct planet
{
char name[LIM];
double population;
double g;
};
const char* file = "Planet.dat";
inline void eatline() { while (cin.get() != '\n')continue; }
int main()
{
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 << "Here are the current contents of the " << file << "file:\n";
while (finout.read((char *)&pl,sizeof pl))
{
cout << ct++ << ": " << setw(LIM) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
}
if (finout.eof())
{
finout.clear();
}
else
{
cerr << "Error in reading" << file << ".\n";
exit(EXIT_FAILURE);
}
}
else
{
cerr << file << "could not be opened--bye.\n";
exit(EXIT_FAILURE);
}
cout << "Enter the record number you wish to change: ";
long rec;
cin >> rec;
eatline();
if (rec<0 || rec >= ct)
{
cerr << "Invalid record bumber --bye \n";
exit(EXIT_FAILURE);
}
streampos place = rec * sizeof pl;
finout.seekg(place);
if (finout.fail())
{
cerr << "Error on attempted seek\n";
exit(EXIT_FAILURE);
}
finout.read((char *)&pl, sizeof pl);
cout << "Your selection:\n";
cout << rec << ": " << setw(LIM) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
if (finout.eof())
{
finout.clear();
}
cout << "Enter planet name: ";
cin.get(pl.name, LIM);
eatline();
cout << "Enter planetary population: ";
cin >> pl.population;
cout << "Enter planet's acceleration of gravity: ";
cin >> pl.g;
finout.seekp(place);
finout.write((char*)&pl, sizeof pl) << flush;
if (finout.fail())
{
cerr << "Error on attempted write\n";
exit(EXIT_FAILURE);
}
ct = 0;
finout.seekg(0);
cout << "Here are the new contents of the " << file << " file:\n";
while (finout.read((char *)&pl,sizeof pl))
{
cout << ct++ << ":" << setw(LIM) << pl.name << ": "
<< setprecision(0) << setw(12) << pl.population
<< setprecision(2) << setw(6) << pl.g << endl;
}
cout << "Done!\n";
return 0;
}
临时文件:
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
cout << "This system can generate up to " << TMP_MAX
<< " temporary names of up to " << L_tmpnam
<< " characters.\n";
char pasName[ L_tmpnam ] = { '\0' };
cout << "Here are ten names:\n";
for (int i = 0;i < 10;i++)
{
tmpnam(pasName);
cout << pasName <<endl;
}
return 0;
}
上面代码可以生成10个零时文件名。