文件基本概念和文件流类
文件的概念
在计算机中,通常将一些内容相关的信息组织起来保存在一起并用一个名字标识,这就是文件。
C++根据文件数据的编码方式不同分为文本文件和二进制文件。
C++文件流类
流是一个逻辑概念,是对所有外部设备的逻辑抽象。
C++标准库中有3个流类可以用于文件操作。
- ifstream:用于从文件中读取数据
- ofstream:用于向文件中写入数据
- fstream:既可用于从文件中读取数据,又可用于向文件中写入数据。
打开和关闭文件
打开文件
在对文件进行读写操作之前,先要打开文件,打开文件有两个目的
- 建立关联;
- 指明文件的使用方式和文件格式。
打开文件的方式有两种
- 先建立流对象,然后调用open()函数连接外部文件
流类名 对象名;
对象名.open(文件名,模式);
- 调用流类带参数的构造函数,在建立流对象的同时连接外部文件。
流类名 对象名(文件名,模式);
表8-1 文件打开模式标记
模式标记 | 适用对象 | 作用 |
---|---|---|
ios::in | ifstream/fstream | 以读方式打开文件。如果文件不存在,则打开出错 |
ios::out | ofstream/fstream | 以写方式打开文件。如果文件不存在,则新建该文件;如果文件已经存在,则打开时清除原来的内容 |
ios::app | ofstream | 以追加方式打开文件,用于在文件尾部添加数据。如果文件不存在,则新建该文件 |
ios::ate | ofstream | 打开一个已有的文件,并将文件读指针指向文件末尾。如果文件不存在,则打开出错。 |
ios::trunc | ofstream | 删除文件现有内容。单独使用时与ios::out相同 |
ios::binary | ifstream/ofstream/fstream | 以二进制方式打开文件。若不指定此模式,则以默认的文本模式打开文件 |
ios::in | ios::out | fstream/ofstream | 打开已存在的文件,即可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。 |
ios::in |ios::out|ios::trunc | fstream | 打开文件,即可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容,如果不存在,则新建。 |
例如,要从data.txt中读取数据
ifstream inFIle;
inFile.open("data.txt",ios::in);
或
ifstream inFIle("data.txt",ios::in);
关闭文件
使用fstream中的成员函数close()关闭文件。
程序8-1 建立流对象,然后调用open()函数连接外部文件
#include
#include
using namespace std;
int main()
{
ifstream inFile;
inFile.open("d:\\tmp\\test.txt",ios::in);
if(inFile)
{
cout<<"成功打开文件:d:\\tmp\\test.txt\n";
inFile.close();
}
else
cout<<"打开文件失败:d:\\tmp\\test.txt\n";
ofstream outFile;
outFile.open("test1.txt",ios::out);
if(!outFile)
cout<<"error1"<
程序8-2 调用流类带参数的构造函数打开文件
#include
#include
using namespace std;
int main()
{
ifstream inFile("d:\\tmp\\test.txt",ios::in);
if(inFile)
{
cout<<"成功打开文件:d:\\tmp\\test.txt\n";
inFile.close();
}
else
cout<<"打开文件失败: d:\\tmp\\test.txt\n";
ofstream outFile("test1.txt",ios::out);
if(!outFile)
{
cout<<"error1"<
文件读写操作
读写文本文件
C++将文件看成顺序排列的无结构的字节流。
程序8-3 对文本文件score.txt进行输入/输出
#include
#include
using namespace std;
int main()
{
char id[11],name[21];
int score;
ofstream outFile;
outFile.open("score.txt",ios::out);
if(!outFile)
{
cout<<"创建文件失败"<>id>>name>>score)
outFile<
输入如下:
内容如下
程序8-4 读入学生成绩文件score.txt并显示内容
#include
#include
#include
using namespace std;
int main()
{
char id[11],name[21];
int score;
ifstream inFile;
inFile.open("score.txt",ios::in);
if(!inFile)
{
cout<<"打开文件失败"<>id>>name>>score)
cout<
程序8-5 读入文本文件,加上行号后显示内容
#include
#include
#include
using namespace std;
int main()
{
char ch,filename[20];
int count=0;
bool newline = true;
cout<<"请输入文件名: ";
cin>>filename;
ifstream inFile(filename,ios::in);
if(!inFile)
{
cout<<"打开文件失败"<
程序8-6 对文本文件的内容排序,将结果输出到另一个文件
#include
#include
#include
using namespace std;
const int MAX_NUM = 1000;
class CStudent
{
public:
char id[11]; //学号。为10位,以'\o'结尾
char name[21]; //姓名。不超过20个字符
int score; //成绩
}stu[MAX_NUM]; //存放文件中读入的整数
int MyCompare(const void * e1,const void * e2)
{
return (*(CStudent *)e1).score-(*(CStudent *)e2).score;
}
int main()
{
ifstream srcFile("score.txt",ios::in);
if(!srcFile)
{
cout<<"opening source file error."<>stu[n].id>>stu[n].name>>stu[n].score)
{
cout<
读写二进制文件
文本文件在存储数据时是以ASCII码形式保存数据的。二进制数据文件以基本类型数据的二进制形式存放。
C++用binary方式打开二进制文件,调用ifstream或fstream的read()成员函数从文件中读取数据,调用ofstream或fstream的write()成员函数向文件中写入数据。
- 用ostream::write()成员函数写文件
ostream和fstream的write()成员函数继承自ostream类。
ostream & write(char *buffer,int nCount);
程序8-7 用二进制文件保存学生信息
#include
#include
using namespace std;
class CStudent
{
public:
char id[11];
char name[21];
int score;
};
int main()
{
CStudent stu;
ofstream outFile("students.dat",ios::out|ios::binary);
if(!outFile)
{
cout<<"创建文件失败"<>stu.id>>stu.name>>stu.score)
outFile.write((char *)&stu,sizeof(stu));
outFile.close();
return 0;
}
程序8-8 向二进制文件中追加数据
#include
#include
using namespace std;
class CStudent
{
public:
char id[11];
char name[21];
int score;
};
int main()
{
char ch;
cout<<"确实需要向文件中追加新数据吗(Y/N)?";
cin>>ch;
if(ch=='Y' || ch=='y')
{
CStudent stu;
ofstream outFile("students.dat",ios::app|ios::binary);
if(!outFile)
{
cout<<"以追加方式打开文件失败"<>stu.id>>stu.name>>stu.score)
outFile.write((char*)&stu,sizeof(stu));
outFile.close();
}
return 0;
}
- 用istream::read()成员函数读文件
继承自类istream
istream &read(char * buffer,int nCount);
- 用ostream::gcount()成员函数得到读取字节数
int gcount();
程序8-9 从二进制文件中读取数据
#include
#include
#include
using namespace std;
class CStudent
{
public:
char id[11];
char name[21];
int score;
};
int main()
{
CStudent stu;
int count=0,nbyte=0;
ifstream inFile("students.dat",ios::in|ios::binary);
if(!inFile)
{
cout<<"创建文件失败"<
用成员函数put()和get()读写文件
可以用类ifstream和类fstream的成员函数get()从文件中一次读取一个字节,也可以用类ofstream和类fstream的成员函数put()向文件中一次写入一个字节。
函数get()有3中主要形式
- int get();
- istream& get(char &rch);
- istream & get(char *pch,int nCount,char delim='\n');
函数put()语法格式
ostream &put(char ch);
程序8-10 文件复制
#include
#include
using namespace std;
int main(int argc,char * argv[])
{
if(argc != 3) //判断main的参数是否位3个
{
cout<<"使用方法错误。正确的命令格式:mycopy SourceFile NewFile"<
随机访问文件
如果一个文件只能进行顺序存取操作,称为顺序文件。典型的是键盘、显示器和保存在磁带上的文件。
如果一个文件可以在文件的任意位置进行存取操作,称为随机文件。磁盘文件就是随机文件。
在访问文件的过程中,若严格按照数据保存的次序从头到尾访问文件,则称为顺序访问。
若不必按照数据的存储次序访问文件,而是要根据需要在文件的不同位置进行访问,则称为随机访问。
在C++中,每个流都有一个”流指针“,由系统控制,会随着对流的各种操作在字节流中移动。
在类istream、类ifstream和类fstream中有成员函数seekg(),可以设置文件读指针的位置;
在类ostream、类ofstream和类fstream中有成员函数seekp(),可以设置文件的写指针位置。
类istream中与位置指针相关的函数
移动读指针函数
istream & seekg(long pos);将读指针设置为pos。
istream & seekg(long offset,ios::seek_dir dir); 将读指针按照seek_dir的指示移动offset个字节。返回读指针当前位置值的函数
long tellg(); 返回值为流中读指针的当前位置。
类ostream中与位置指针相关的函数
移动写指针函数
ostream & seekp(long pos);
ostream & seekp(long offset,ios::seek_dir dir);返回写指针当前位置的函数
long tellp();
程序8-11 修改程序8-7,
#include
#include
#include
using namespace std;
class CStudent
{
public:
char id[11];
char name[21];
int score;
};
int main()
{
CStudent stu;
int count = 0,nbyte=0;
ifstream inFile("students.dat",ios::in|ios::binary);
if(!inFile)
{
cout<<"创建文件失败"<
程序8-12 读取文件,查找最高分和最低分的学生,并显示信息。
#include
#include
#include
using namespace std;
class CStudent
{
public:
char id[11];
char name[21];
int score;
};
int main()
{
CStudent stu;
int count=0,maxScore,minScore,maxNo,minNo;
maxScore = INT_MIN;
minScore = INT_MAX;
maxNo = minNo = 0;
ifstream inFile("students.dat",ios::in|ios::binary);
if(!inFile)
{
cout<<"创建文件失败"< maxScore)
{
maxScore = stu.score;
maxNo = count;
}
else if(stu.score < minScore)
{
minScore = stu.score;
minNo = count;
}
count++;
}
inFile.clear();
inFile.seekg(sizeof(CStudent)*maxNo,ios::beg);
inFile.read((char *)&stu,sizeof(CStudent));
cout<<"最高分记录: "<