第 12章 文 件 处 理
12.1 文 件 简 介
12.2 文 件 和 流
12.3 顺序文件的访问
12.4 随机文件的访问
12.1 文 件 简 介
C++的文件一般指存储在外部介质上的数据集合。
这里的外部存储介质一般特指磁盘,磁盘上的文件称为磁盘文件 。 对磁盘文件的输入 /输出简称为文件 I/O。
每个文件都对应一个文件名,
文件名由文件主名和扩展名两部分组成,
它们之间用圆点分开 。 文件主名是由用户命名的一个有效的 C++标识符,为了便于记忆和使用,一般使文件主名的含义与所存的文件内容相一致 。
文件扩展名是由用户命名的 1~3个字符组成,
是有效的 C++标识符,通常用它来区分文件的类型 。
在 C++程序中保存数据的文件按存储格式分为两种类型,一种为 ASCII码文件或文本文件,它的每一个字节存放一个 ASCII代码,代表一个字符。另一种为内部格式文件或二进制文件,是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。
12.2 文 件 和 流
C++语言把文件看作是一个字符(字节)
的序列,即由一个一个字符(字节)的数据顺序组成。一个文件是一个字节流或二进制流。它把数据看作是一连串的字符
(字节),而不考虑记录的界限。
这种以字节流或二进制流组成的文件被称为流式文件 。 以字符为单位进行操作增加了处理的灵活性 。
为了进行文件 I/O操作,C++定义了文件流 。
文件流是控制台流的扩展,是从控制台流类派生来的,它继承了控制台流类的所有特点 。 文件流类根据自己的需求,增加了控制台流类所没有的特性 。
文件流可分为 3类:输入文件流 ifstream、
输出文件流 ofstream以及输入 /输出文件流
fstream。
和其他高级语言一样,对文件的读写之前应打开该文件,在完成操作之后应及时关闭该文件 。
调用相应流中的 open成员函数或构造函数,
按照一定的打开方式打开一个文件 。
open的函数原型为:
void open( const char* szName,int nMode,
int nProt = filebuf::openprot );
其中,szName是文件名,它可包含驱动器符和路径说明; nMode说明文件打开的模式,
表 13.1给出了 nMode的取值范围 。
关闭任何一个流对象所对应的文件,就是用这个流对象调用 close( ) 成员函数即可 。
表 13 - 1 流模式标志选 项
io s:,a p p 添加模式,所有新数据都写入文件尾部。
io s:,a te 打开文件时文件指针定位到文件尾,如果程序移动了文件指针,就把数据写入到当前位置。
io s:,in 打开文件进行读操作,文件不存在时出 错。
io s:,o u t 打开文件进行写操作,如文件已存在则更新该文件。
io s:,tru n c 如果文件已存在则清空原文件
io s:,n o c re a te 打开一个已经存在的文件,如果文件不存在则打开失败。
io s:,n o re p lac e 打开一个不存在的文件,如果文件存在则打开失败。
io s:,b in a ry 二进制文件(非文本文件)
12.3 顺序文件的访问对文件的操作总是从文件指针位置开始顺序向后移动,所以称之为顺序文件。
12.3.1 建立顺序访问文件
1,建立文本文件
【 12.1】 使用操作器、设置标志位和成员函数向输出文件中输出文本。
#include <fstream.h>
#include <stdlib.h>
#include <iomanip.h>
void main(void)
{
fstream output;
output.open("d:\\data\\test.dat",ios::out);
if(output.fail())
{
cerr<<"Can not open test.dat"<<endl;
//打开文件错误时,给出错误提示
abort();
//终止程序运行
}
output<<setiosflags(ios::left)<<setw(13)<<"
Name"<<setw(10)<<"Class"
<<setw(10)<<"Age"<<endl;
output<<setiosflags(ios::left)<<setw(13)<<"
Zhang San"<<setw(10)<<10
<<setw(10)<<21<<endl;
output<<setiosflags(ios::left)<<setw(13)<<"
Li Si"<<setw(10)<<10
<<setw(10)<<19<<endl;
output<<setiosflags(ios::left)<<setw(13)<<"
Wang Wu"<<setw(10)<<10
<<setw(10)<<20<<endl;
output<<setiosflags(ios::left)<<setw(13)<<"
Zhao Liu"<<setw(10)<<10
<<setw(10)<<22<<endl;
for(char ch='a';ch<='z';ch++)
output.put(ch);
output.write("\n1234567890",11);
output.close();
}
输出到 d:\data\test.dat文件中的数据为:
Name Class Age
Zhang San 10 21
Li Si 10 19
Wang Wu 10 20
Zhao Liu 10 22
abcdefghijklmnopqrstuvwxyz
1234567890
2,建立二进制文件为执行二进制文件操作,必须首先使用
ios::binary模式指示符打开文件 。
【 12.2】 打开一个二进制文件并向其中写入数据 。
#include <stdlib.h>
#include <fstream.h>
void main(void)
{
fstream output;
output.open("d:\\data\\binary_data.dat",io
s::out|ios::binary);
if(!output)
{
cerr<<"Can not open
binary_data.dat"<<endl;
abort();
}
double
x[]={3.1415926,6.2831852,9.4247778,12.566
3704,15.707963};
for(int i=0;i<5;i++)
output.write((char*)&x[i],sizeof(double));
//write成员函数
output.close();
}
12.3.2 读取顺序文件中的数据
1,读取文本文件
【 12.3】 读取文件内容到显示器 。
#include <fstream.h>
#include <stdlib.h>
void main(void)
{
fstream input("d:\\data\\test.dat",ios::in);
if(input.fail())
{
cerr<<"Can not open test.dat"<<endl;
abort();
}
while(!input.eof())
{
cout.put((char)input.get());
}
}
2,读取二进制文件
【 12.4】 读写二进制文件 。 该程序先打开输入文件,在文件中输入二进制数据,关闭文件 。 然后再打开该文件,从中读二进制数据并显示在屏幕上 。
#include <stdlib.h>
#include <fstream.h>
#include <iomanip.h>
void main(void)
{
fstream output;
output.open("d:\\data\\binary_data.dat",io
s::out|ios::binary);
if(!output)
{
cerr<<"Can not open
binary_data.dat"<<endl;
abort();
}
double
x[]={3.1415926,6.2831852,9.4247778,12.566
3704,15.707963};
for(int i=0;i<5;i++)
output.write((char*)&x[i],sizeof(double));
output.close();
fstream
input("d:\\data\\binary_data.dat",ios::in|io
s::binary);
double z[5];
if(input.fail())
{
cerr<<"Can not open
binary_data.dat"<<endl;
abort();
}
for(i=0;i<5;i++)
{
input.read((char*)&z[i],sizeof(double)
);
cout<<setprecision(10)<<z[i]<<endl;
}
input.close();
}
运行程序,输出结果为:
3.1415926
6.2831852
9.4247778
12.5663704
15.707963
12.3.3 更新顺序文件中的数据对于一个已经存在的文件,可以用添加的方式修改文件的内容 。
【 12.5】 在文件 d:\\data\\test.dat尾部输出一行字符,Liu Ba 10 18
#include <fstream.h>
#include <stdlib.h>
#include <iomanip.h>
void main(void)
{
fstream output;
output.open("d:\\data\\test.dat",ios::app);
if(output.fail())
{
cerr<<"Can not open test.dat"<<endl;
abort();
}
output<<setiosflags(ios::left)<<setw(13)<<"
Liu Ba"<<setw(10)<<10
<<setw(10)<<18<<endl;
output.close();
}
12.4 随机文件的访问
12.4.1 建立随机访问文件通过控制文件指针的定位,程序可以对文件中某一特定位置进行读写操作 。
这就是所谓的随机访问文件 。
【 12.6】 随机文件的建立和存取。假定有
10名学生的姓名、学号、年龄、性别、总成绩等数据,假定需要读取第 1,3,5,7、
9个学生的数据。
#include <stdlib.h>
#include <fstream.h>
struct student_info
{
char name[20];
int num;
int age;
char sex;
double score;
};
void main(void)
{
student_info cls1[]={
"zhao",1,20,'M',290.5,
"qian",2,19,'M',282.5,
"sun",3,20,'F',288.5,
"li",4,21,'M',275.5,
"zhou",5,22,'M',256.5,
"wu",6,20,'F',289.5,
"zheng",7,19,'M',265.5,
"wang",8,20,'F',278.5,
"feng",9,21,'F',268.5,
"chen",10,20,'F',287.5,
};
fstream
inout("random.dat",ios::out|ios::in|ios::bin
ary);
if(!inout)
{
cerr<<"Can not open
random.dat"<<endl;
abort();
}
for(int i=0;i<10;i++)
inout.write((char*)&cls1[i],sizeof(cls1[i]));
student_info cls2[10];
for(i=0;i<10;i+=2)
{
inout.seekg(i*sizeof(cls1[i]),ios::beg);
inout.read((char*)&cls2[i],sizeof(cls2));
cout<<cls2[i].name<<"\t"<<cls2[i].num
<<"\t"<<cls2[i].age<<"\t"
<<cls2[i].sex<<"\t"<<cls2[i].score<<"\t
"<<endl;
}
inout.close();
}
运行程序,输出结果为:
zhao 1 20 M 290.5,
sun 3 20 F 288.5,
zhou 5 22 M 256.5,
zheng 7 19 M 265.5,
feng 9 21 F 268.5,
12.4.2 读取随机文件中的数据
【 12.7】 在一个文件中存入一串整型数据,
根据屏幕提示输入序号,显示文件指针的位置和数据 。
#include <stdlib.h>
#include <fstream.h>
void main(void)
{
fstream
inout("random_r.dat",ios::out|ios::in|ios::b
inary);
if(!inout)
{
cerr<<"Can not open
random_r.dat"<<endl;
abort();
}
for(int i=0;i<100;i++)
inout.write((char*)&i,sizeof(int));
int n,m;
cout<<"Please type in a number:between
0-99"<<endl;
cin>>n;
inout.seekg(n*sizeof(int),ios::beg);
cout<<"The positon of file pointer after
read is,"<<inout.tellg()<<endl;
inout.read((char*)&m,sizeof(int));
cout<<"The data you read is,"<<m<<endl;
}
运行程序,输出结果为:
Please type in a number:between 0-99
8( 注:此数据为用户通过键盘输入的,输入完毕请回车 )
The positon of file pointer after read is,32
The data you read is,8
12.4.3 数据写入随机文件
【 12.8】 程序先建立一个随机文件,然后将指定位置的数据用新数据代替,最后显示写入的数据。
#include <stdlib.h>
#include <fstream.h>
void main(void)
{
fstream
inout("random_w.dat",ios::out|ios::in|ios::
binary);
if(!inout)
{
cerr<<"Can not open
random_w.dat"<<endl;
abort();
}
for(int i=0;i<=10;i++)
inout.write((char*)&i,sizeof(int));
cout<<"Please input n,0<=n<=10 "<<endl;
int n;
cin>>n;
inout.seekp(n*sizeof(int),ios::beg);
int m=100;
inout.write((char*)&m,sizeof(int));
inout.seekg(0,ios::beg);
int nd;
for(i=0;i<=10;i++)
{
inout.read((char*)&nd,sizeof(int));
cout<<nd<<endl;
}
inout.close();
}