《Visual C++ 6.0程序设计》课件第4章_第1页
《Visual C++ 6.0程序设计》课件第4章_第2页
《Visual C++ 6.0程序设计》课件第4章_第3页
《Visual C++ 6.0程序设计》课件第4章_第4页
《Visual C++ 6.0程序设计》课件第4章_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章文件操作4.1文件的基本概念4.2顺序文件操作4.3随机文件操作4.4二进制文件操作思考题

4.1文件的基本概念

在前面的程序中,所处理的数据都是直接写在程序中,或在程序运行时通过键盘输入的,程序处理的结果由屏幕输出。当程序需要处理大量的数据时,就不可能采用这种方法。程序中的数据在运行结束后就会从内存中消失,再次运行程序时不会出现,因此有必要将这些数据通过文件的形式保存起来。下面将主要讲述文件的基本概念。4.1.1文件与流的概念

文件是存储在外部介质上的用文件名标识的数据的集合。其中外部介质主要是硬盘,也可以是光盘、优盘、软盘等。通常情况下,大量的数据都是以文件的形式存放的,每个操作系统都提供相应的文件系统来对文件进行存取。每个文件应有一个包含设备和路径信息的文件名。

文件只与信息的输入和输出操作相关,而这些输入和输出是串行序列形式,于是人们将文件的概念抽象为“流”。流是程序设计对I/O系统中文件的抽象。流具有方向性,分为输入流和输出流,并分别称为源和汇。前面章节中已经使用的cin和cout就是流对象,分别称为标准输入流对象和标准输出流对象,“<<”和“>>”表示数据流动的方向。对文件进行输入输出操作,必须通过“打开文件”的操作将一个文件和一个流联系起来,也就是构造输入输出文件流对象。一旦建立了联系,以后对该流的访问就是对该文件的访问,也是对一个具体设备的访问。可以通过“关闭文件”的操作断开它们之间的联系。4.1.2文件及其结构

一个文件通常是由若干个记录组成的,而一个记录中往往又包含了若干个数据项。

1.记录

记录是电脑处理数据的基本单位,它由若干个相互关联的数据项组成,数据项是文件中最基本的不可分的数据单位。记录一般具有相同的性质和结构。例如:进行通讯录管理时,每个人的信息组成一个记录,该记录由序号、姓名、性别、生日、电话、邮箱等数据项组成,如下所示。

文件在保存时通常有一个或多个数据项作为关键字,它必须能区分该记录和其他记录,比如可以将序号定义为关键字,因为每个人的序号不同,也可以将姓名定义成关键字,但性别却不能作为关键字。

2.文件的种类

根据文件中数据的组织方式,文件可以分为文本文件和二进制文件。文本以字节为单位,每个字节对应一个ASCII码,表示一个字符,也称字符文件,在输入输出过程中系统要对内外存数据格式进行相应转换。而二进制文件以字位为单位,实际上是由0和1组成的序列,输入输出过程中系统不对数据格式进行转换。

根据文件的读写方式,可以将文件分为顺序文件和随机文件。

4.2顺序文件操作

顺序文件的各个记录顺序地存放在外部介质的连续区域。对于顺序文件的操作通常有三个步骤:打开文件、读写文件、关闭文件。

4.2.1顺序文件的打开和关闭

在使用顺序文件之前,必须进行打开文件操作,在使用完一个文件后,也必须进行关闭文件操作。

1.顺序文件的打开

为了对顺序文件进行读写操作,必须首先打开文件,读写操作完成后再关闭。文件的打开方式有3种,分别通过使用ifstream类、ofstream类、fstream类成员函数来实现。

(1) ifstream类:支持从本流类(对象)所对应的磁盘文件中读入数据。

(2) ofstream类:支持从本流类(对象)所对应的磁盘文件中写出数据。

(3) fstream类:支持从本流类(对象)所对应的磁盘文件中读入和写出数据的双向操作。

定义ifstream类的对象,其一般形式为:

ifstream<对象名>;

<对象名>.open(“<文件名>”);

为了书写简便,可以将上面两条语句合并写成:ifstream<对象名>(“<文件名>”);

定义ofstream类的对象,其一般形式为:

ofstream<对象名>;

<对象名>.open(“<文件名>”);

同样,可以将上面两条语句合并写成:ofstream<对象名>(“<文件名>”);

定义fstream类的对象,其一般形式为:

fstream<对象名>;

<对象名>.open(“<文件名>”,<模式>);同样,可以将上面两条语句合并写成:fstream<对象名>(“<文件名>”,<模式>);

open函数原型:

voidopen(constchar*filename,intfilemode,intprot=filebuf::openprot);

(1) open:关键字,表示将指定的文件按某种方式打开。

(2) filename:即文件名,指定要打开的文件的文件名,包括路径。

(3) filemode:即访问模式,文件的访问模式如表4-1所示。表4-1文件的访问模式

filemode可以缺省,当文件流为输入文件流时,其缺省值为in;为输出文件流时,其缺省值为out。如果需要,可以用位运算符进行组合来表示所需的访问模式。例如:

ios::in|ios::out//以可读可写的方式打开文件

(4)prot:指定打开文件的保护方式,它与具体的操作系统有关,一般用缺省值“filebuf::openprot”表示DOS兼容的方式。

例如:

如果要打开“D:\VC++程序设计\第4章”目录下的一个文件名为“file1.txt”的文件,向文件写入数据,则命令应写为:

fstreamoutfile1; //定义文件流类fstream的一个对象outfile1

outfile1.open(“D:\VC++程序设计\第4章\file1.txt”,ios::out);

//调用该对象的open函数打开并写文件“file1.txt”

2.顺序文件的关闭

文件操作完成后必须及时关闭,关闭操作可以将内存中尚未写入文件的数据写入文件,并切断与内存的联系。

关闭流类的对象,其一般形式为:

<对象名>.close();

close函数原型:

voidclose()

例如:

如果要关闭上面的“file1.txt”的文件,则命令应写为:

outfile1.close();//关闭已打开的outfile1流对象4.2.2文件的读写

打开顺序文件后,就可以对文件进行读写操作了。下面分别介绍文件的写操作和读操作。

1.写操作

顺序文件的写操作是指写入文件的数据在文件中的存放位置是连续的。

将数据写入顺序文件所用的命令是:put()函数以及插入符“<<”。

put()函数的一般形式为:

put(charch);

put()函数用来将字符变量ch中存放的字符写到输出文件中,即向文件中写入一个字符。

【例4-1】

利用put()函数将字符串“Thisisanexampleoftheuseoffunctionput().”顺序写入文件。

程序如下:

#include“stdafx.h”

#include<fstream.h>//fstream类头文件

#include<iostream.h>

intmain(intargc,char*argv[])

{

char*str=“Thisisanexampleoftheuseoffunctionput().”;

ofstreamoutfile2;

//定义文件流类fstream的一个对象outfile2

outfile2.open(“text1.txt”,ios::out);

//在当前路径下建立并打开文件"text1.txt"

if(!outfile2) //判断该文件是否打开 {

cout<<''text1.txtopenerror!''<<endl;

return0;

}

for(inti=0;str[i]!='\0';i++)

outfile2.put(str[i]);

//利用put函数把数据顺序写入文件

outfile2.close(); //不要忘记文件使用结束后要及时关闭

return0;

}

程序运行后,在当前路径上建立了一个名为“text1.txt”的文本文件。程序运行过程中,执行到outfile2.open("text1.txt",ios::out);语句,如果磁盘上没有文本文件“text1.txt”,系统就会自动新建一个文本文件“text1.txt”,如果磁盘上已有文本文件"text1.txt",则会覆盖原来的文件。用写字板打开“text1.txt”,如图4-1所示。图4-1文本文件"text1.txt"

2.读操作

对于一个已经建立好的顺序文件,可以通过读操作从文件的读写位置开始依次顺序读取数据。

读顺序文件所用的命令是:get()函数和getline()函数以及提取符“>>”。

1) get()函数

get()函数的一般形式为:

get(char&ch);

get()函数用来从文件中读取一个字符。

2) getline()函数

getline()函数的一般形式为:

getline(char*pch,intcount,chardelim= ‘\n’);

getline()函数用来从文件中读取多个字符,其中字符的个数由count指定,delim是读取字符时指定的结束符。

下面的例题分别使用get()函数和getline()函数进行文本文件的读操作,请注意比较这两个函数的异同。

【例4-2】

分别利用get()函数和getline()函数读出例4-1生成的顺序文件“text1.txt”。

方法1:利用get()函数读操作。

程序如下:

#include''stdafx.h''

#include<fstream.h> //fstream类头文件

#include<iostream.h>

intmain(intargc,char*argv[])

{

charstr[100];

inti=0;

ifstreaminfile1; //定义文件流类fstream的一个对象infile1

infile1.open("text1.txt",ios::in);

//在当前路径下打开并读文件“text1.txt”,如果该路径下没有该文件可在文件名前加上适当的路径名,也可将例4_1生成的“text1.txt”复制到当前路径下

if(!infile1) //判断该文件是否打开

{

cout<<“text1.txt文件没有打开!”<<endl;

return0;

}

//比较标记开始

while(infile1)

{

infile1.get(str[i]); //利用get函数从顺序文件读取数据

i++;

} str[i]='\0'; //将字符串尾符‘\0’作为串结束标志

//比较标记结束

infile1.close();

cout<<str<<endl; //输出所读入的内容

return0;

}

程序运行结果如图4-2所示。图4-2读顺序文件运行结果方法2:利用getline()函数读操作。

该函数的使用只需将上面的程序中从“//比较标记开始”到“//比较标记结束”的语句改为如下语句,程序的运行结果和上面的程序完全相同。

程序如下:

while(infile1)

{

infile1.getline(str,sizeof(str),'0'); //读取整个文件

cout<<str; //输出所读取的内容

} 利用getline()函数不仅可以从文件读数据,也可以从键盘输入读数据。下面的例题介绍如何通过键盘输入读取数据。

【例4-3】

利用getline()函数从键盘读入3行数据,显示在屏幕上,并将这3行数据写入文件“text2.txt”。

程序如下:

#include"stdafx.h"

#include<fstream.h>//fstream类头文件

#include<iostream.h>

intmain(intargc,char*argv[])

{

ofstreamfile1;//定义文件流类fstream的一个对象file1

file1.open(“text2.txt”,ios::out);

if(!file1)

{

cout<<“text2.txtopenerror!”<<endl;

return0;

}

chars[3][100];

cout<<“输入3行数据:”<<endl;

for(inti=0;i<3;i++)

cin.getline(s[i],100,‘\n’);//每次从键盘输入一行

cout<<“----------------------------------”<<endl;//分隔输入和输出的内容

for(i=0;i<3;i++)

{ cout<<s[i]<<endl;//输出所读取的内容

file1<<s[i]<<endl;//写入文件text2.txt

}

file1.close();//不要忘记文件使用结束后要及时关闭

return0;

}

程序运行结果如图4-3所示。图4-3利用getline()函数从键盘读运行结果

【例4-4】编写一个程序,用来拼接两个顺序文件的内容,其结果保存到第一个文件中。

提示:先将例4-1生成的“text1.txt”和例4-3生成的“text2.txt”复制到当前路径下,运行程序后两个文件的内容就保存在“text1.txt”中。

程序如下:

#include“stdafx.h”

#include<fstream.h>

#include<iostream.h>

#include<stdlib.h>

#include<stdio.h>

intmain(intargc,char*argv[])

{ charstr[100];

inti=0,file1Length=0,file2Length=0;

fstreamfile1;//定义文件流类fstream的一个对象file1

file1.open("text1.txt",ios::app);

if(!file1)//判断该文件是否打开

{

cout<<"text1.txt文件没有打开!"<<endl;

exit(0);

}

ifstreamfile2;//定义文件流类ifstream的一个对象file2

file2.open("text2.txt",ios::in);

if(!file2)//判断该文件是否打开

{ cout<<"text2.txt文件没有打开!"<<endl;

exit(0);

}

while(file2)

{

file2.get(str[i]);

i++;

}

str[i]='\0';//将字符串尾符'\0'作为串结束标志

for(i=0;str[i]!='\0';i++)

file1.put(str[i]);//利用put函数把数据顺序写入文件

file1.close();

file2.close();

return0;

}程序运行一次后,在当前目录下再打开“text1.txt”,其结果如图4-4所示。图4-4"text1.txt"内容显示在上面的这个例题中,文件名是在程序中设定的,不具有通用性。为了在程序运行时根据需要进行输入,可以将文件名作为程序的参数,由命令行参数来提供。

【例4-5】

将一个文件的内容备份到另一个文件,源文件名和备份文件名由命令行参数提供。

程序如下:

#include"stdafx.h"

#include<fstream.h>

constintMAX=20;//定义文件最大长度

intmain(intargc,char*argv[])

{

if(argc!=3)

{

cout<<"参数个数不正确"<<endl;

return0;

}

charstr[20]; ifstreaminfile(argv[1]);//源文件名

if(!infile)//判断源文件是否打开

{

cout<<"源文件没有打开!"<<endl;

return0;

}

ofstreamoutfile(argv[2]);//备份文件名

if(!outfile)//判断备份文件是否打开

{

cout<<"备份文件没有打开!"<<endl;

return0;

}

while(infile)

{

infile.getline(str,sizeof(infile),'\0');

outfile<<str<<endl;

}

return0;

}该程序文件名为“Chap4_5.cpp”,编写完成后,选择“编译/编译Chap4_5.cpp”命令编译程序,在输出窗口得到“Chap4_5.exe-0error(s),0warning(s)”后,再选择“编译/构件Chap4_5.exe”命令生成可执行文件“Chap4_5.exe”(文件的路径为“D:\VC++程序设计\第4章\Chap4_5\Debug\Chap4_5.exe”),它的功能类似于DOS中的copy命令,使用方法也相同。在Windows命令提示符里(如图4-5所示)输入如下格式的命令:

程序文件名源程序文件名备份文件名

例如:将文件“d:\text1.txt”复制为文件“d:\text1.bak”,具体操作是在命令提示符后

输入:

Chap4_5d:\.text1.txtd:\text1.bak图4-5在命令提示符里运行Chap4_5

4.3随机文件操作

随机文件的读写操作是非顺序的(即随机的),以随机的方式访问文件时,文件的记录为定长格式,即每条记录的长度都是相同的。这样在读写磁盘文件的某一数据前无需读写前面的数据,从而大大提高了存取速度。

在以随机的方式读写文件时,同样要首先打开文件,读写操作完成后再关闭,其所用函数和顺序方式所用的函数相同。

为了方便文本文件和二进制文件的随机读写,VisualC++提供了设置写入和读取文件的读写指针位置函数。文件设置读写指针位置函数可以将文件指针移动到指定的位置。4.3.1随机写

对于文件的写操作,ostream提供了seekp()函数,它有绝对偏移指针设置函数和相对偏移指针设置函数两种形式。

1.绝对偏移指针设置函数

绝对偏移指针设置函数的一般形式为:

ostream&seekp(longpos);

该函数的作用是将写入数据的开始位置定位于距文件首某个指定字节长度的地方。其中,pos是距文件首的绝对偏移量,即文件指针的绝对位置。

例如:在一个已经打开的数据文件指针距文件首10个字节的地方写数据,可以写成:

outfile.seekp(10);//该文件ostream流类对象名为outfile

2.相对偏移指针设置函数

相对偏移指针设置函数的一般形式为:

ostream&seekp(longoff,ios::seek_dirdir);

该函数的作用是将写入数据的开始位置定位于相对于文件某个位置指定字节长度的地方。其中,off是距文件某个位置的相对偏移量,即文件指针的相对位置;ios::seek_dirdir用来指定偏移类型,偏移类型如表4-2所示。表4-2偏移类型例如:在一个已经打开的数据文件指针距当前位置10个字节的地方写数据,可以写成:

file1.seekp(10,ios::cur);//该文件ostream流类对象名为file1

【例4-6】

利用seekp()函数将字母a~z组成的字符串间隔的写入数据文件“字母表.dat”中,相应的偏移量依次为0,3,6,9,…。

程序如下:

#include"stdafx.h"

#include<iostream.h>

#include<fstream.h>

intmain(intargc,char*argv[])

{

charch='a';

charstr[26];//定义表示26个字母的字符串

for(inti=0;i<26;i++)

{

str[i]=ch+i;

cout<<str[i];

}

cout<<endl;

ofstreamfile1("字母表.dat");//打开并新建或写文件

if(!file1)//判断该文件是否打开

{

cout<<"字母表文件没有打开!"<<endl;

return0;

}

for(i=0;i<26;i++)

{ file1.seekp(3*i); //定位

file1.put(str[i]); //写数据

}

file1.close();//关闭文件

return0;

}

程序运行结果如图4-6所示。

程序运行后生成文件“字母表.dat”的内容用记事本方式打开,如图4-7所示。

程序运行后生成文件“字母表.dat”的内容用VisualC++程序打开,效果如图4-8所示。图4-6随机写举例运行结果图4-7在记事本里打开“字母表.dat”文件内容图4-8在VisualC++里的“字母表.dat”文件内容从图4-8中可以看出,写入的字母之间相隔2个字节。小写字母“a”的ASCII码用十六进制表示为61,后面字母依次加1,其中间隔中未写入的地方为00。4.3.2随机读

对于文件的读操作,istream提供了seekg()函数,它有绝对偏移指针设置函数和相对偏移指针设置函数两种形式。

1.绝对偏移指针设置函数

绝对偏移指针设置函数的一般形式为:

istream&seekg(longpos);

该函数的作用是用来设置读取数据的开始位置。其中,pos是距文件首的绝对偏移量,即文件指针的绝对位置。

例如:在一个已经打开的数据文件指针距文件首20个字节的地方开始读数据,可以写成:

file2.seekp(20);//该文件istream流类对象名为file2

2.相对偏移指针设置函数

相对偏移指针设置函数的一般形式为:

ostream&seekp(longoff,ios::seek_dirdir);

该函数的作用是将读取数据的开始位置定位于相对于文件某个位置指定字节长度的地方。其中,off是距文件某个位置的相对偏移量,即文件指针的相对位置。ios::seek_dirdir用来指定偏移类型,偏移类型见表4-2。

例如:在一个已经打开的数据文件指针距当前位置30个字节的地方读取数据,可以写成:

File2.seekp(30,ios::cur);//该文件istream流类对象名为file2

【例4-7】

利用seekg()函数将例4-6生成的“字母表.dat”数据文件的内容逆序输出,即实现文件的倒读功能。

程序如下:

#include“stdafx.h”

#include<iostream.h>

#include<fstream.h>

intmain(intargc,char*argv[])

{

inti=0,len=0;//len表示文件长度

charstr[100];

ifstreamfile2("字母表.dat");//打开并新建或写文件

if(!file2)//判断该文件是否打开

{ cout<<"文件没有打开!"<<endl;

return0;

}

while(file2>>str[i])//求出文件长度

{

len++;

}

cout<<"文件长度为:"<<len<<endl;

cout<<"文件倒读为:";

file2.close();//关闭文件

file2.open("字母表.dat",ios::ate);//打开文件并将指针指定到文件尾

while(i<len)

{ file2.seekg(-i-1,ios::end);

//设定相对于文件尾的偏移量(负数)

file2.get(str[i]);//读取数据

cout<<str[i];//输出数据

i++;

}

file2.close();//关闭文件

cout<<endl;

return0;

}

程序运行结果如图4-9所示。图4-9随机读举例运行结果

4.4二进制文件操作

前面已经讲过按文本方式读写文件,下面介绍按二进制方式读写文件。

与按文本方式读写不同,按二进制方式读写文件有VisualC++语言提供的专门函数,即write()函数和read()函数。

write()函数的一般形式为:

write(constchar*pch,intcount);

write()函数用来向二进制文件中写入多个字符,其中字符的个数由count指定。

read()函数的一般形式为:

read(constchar*pch,intcount);

read()函数用来从二进制文件中读取多个字符,其中字符的个数由count指定。

需要注意的是:打开二进制文件时,要在open()函数中将访问模式设置为ios::binary。

采用二进制方式读写文件的优点是便于对数据进行随机访问,存取效率高;可以对文件进行压缩处理,存储密度大;数据文件便于保密等。它的缺点是兼容性低,不可利用文字处理程序进行阅读或编辑修改等。因此通常将纯文本信息以文本文件方式存储,而将数值信息以二进制方式存储。

【例4-8】

利用write()函数把数据写入二进制文件。程序如下:

#include"stdafx.h"

#include<iostream.h>

#include<fstream.h>

intmain(intargc,char*argv[])

{

inta[10]={0};//定义数组

for(inti=0;i<9;i++)

{

a[i+1]=a[i]*10+i+1;

cout<<a[i]<<endl;

}

cout<<"----------------------------------------"<<endl; ofstreamouttxt("ot.txt");//打开text

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论