实验6 文件系统.docx
《实验6 文件系统.docx》由会员分享,可在线阅读,更多相关《实验6 文件系统.docx(13页珍藏版)》请在冰点文库上搜索。
实验6文件系统
实验6文件系统
一、实验目的:
理解文件操作的基本原理,基本函数,能够正确的使用文件函数实现文件的读写等操作。
二、实验内容:
(1)实现矩阵的随机生成、存放、读取、计算、将计算结果存放到文件中。
主要分为以下步骤:
(1.1)使用动态申请内存的方法(new或者malloc)生成矩阵A和B,并使用随机数为矩阵中的元素赋值;
(1.2)把生成的矩阵A和B存放到文件matrix.txt中。
(1.3)读取存放在matrix.txt中的矩阵,将读取的矩阵内容存放到内存中的矩阵变量【二维数组】中。
(1.4)计算两个矩阵的乘积。
(1.5)将计算结果保存到result.txt中。
(2)编写一个程序,能够复制一个文件(文本文件或二进制文件)。
源文件名和目标文件名由用户输入。
注意:
文件读取或写入应该使用“rb”或“wb”二进制模式。
(3)编写一个程序,能够处理文本文件,实现文本替换的功能,类似word的替换功能。
需要查找和替换的词语通过键盘输入,或者从某个指定文件中读取。
三、实验要求:
(1)理解并掌握文件操作函数的用法
(2)自己编程,独立完成实验任务。
参考资料:
一、实验中用到的C语言文件操作函数
(1)FILE文件描述符的定义:
typedefstruct
{
int_fd; /*文件号*/
int_cleft; /*缓冲区中剩下的字节数*/
int_mode; /*文件操作模式*/
char*_nextc;/*下一个字节的位置*/
char*_buff; /*文件缓冲区位置*/
}FILE;
(2)用于读文件的文件打开形式:
FILE*fsPtr;//定义一个文件指针
constcharDiskName[]="FileSys.dat";//文件名
fsPtr=fopen(DiskName,"rb");
◆第一个参数指明需要打开的文件名
◆r表示读文件,b表示以二进制形式打开文件
◆如果不能打开指定的文件,fopen()函数返回NULL;
◆若能打开文件,返回该文件的文件描述符指针,类型为FILE*型。
(3)用于写文件的文件打开形式:
fsPtr=fopen(DiskName,"wb");
◆若DiskName所指明的文件存在,则文件内容将清空,长度截断为0,若文件不存在,则创建,w表示写文件,b表示是以二进制形式打开文件
(4)以二进制形式向文件中写入内容
charrw_buffer[512];
fwrite(rw_buffer,512,1,fsPtr);
◆fwrite函数的原型为:
fwrite(constvoid*ptr,size_tsize,size_tnMember,FILE*fp)
◆第一个参数ptr指向要写入内容的内存起始地址(即rw_buffer参数值),
◆第二个参数size指明要写入的数据块的大小(512表示每个数据块大小为512字节),size_t是一种通用数据类型,通常表示无符号整型。
◆第三个参数nMember指明要写入的数据块数量(联系第二个参数,参数二是每个数据块的大小)(1表示一共要写入一个数据块),所以,写入文件的总数据量为size*nMember字节。
◆第四个参数fp是要写入内容的文件指针,其类型为FILE*型。
注意,调用fwrite()函数前,必须先用“wb”方式打开文件。
你可以将数据块与结构体做类比,例如每个学生的信息定义为一个结构体,要写入班级70名同学的信息,则写法如下:
structstudent{intnumber;intage;doublescore;};
constintstuTotalNum=70;
structstudentstuArray[stuTotalNum];
FILE*fp;
fp=fopen(“student.dat”,“wb+”);
if(fp==NULL){printf(“Openfilestudent.daterror.Exit.\n”);exit
(1);}//如果打开文件出错,则退出程序
fwrite(stuArray,sizeof(student),stuTotalNum,fp);
(5)以二进制形式从文件中读出内容:
◆fread()函数,该函数原型为:
size_tfread(constvoid*ptr,size_tsize,size_tnMember,FILE*fp);
◆作用:
从fp指向的文件中,读取nMember个数据块,每个数据块的大小为size,读取的内容写到ptr所指向的内存中。
返回值为成功读入的数据块数量。
(6)rewind()函数
◆原型:
voidrewind(FILE*fp)
◆作用:
使文件fp的位置指针指向文件开始。
文件指针FILE*fp中,包含一个读写位置指针char*_nextc,它指向下一次文件读写的位置。
当文件刚打开或创建时,该指针指向文件的开始位置。
随着文件内容的读取或写入,该指针随之变化,始终指向下一次文件读写的位置。
如果想让文件的读写指针再次回到文件的开始位置,则需要调用rewind()函数。
(7)文件读写指针随机移动的函数:
fseek()
◆rewind()函数只能把文件读写指针移动至文件的开始处,如果想根据需要移动到文件中的任意位置,那么需要fseek()函数。
◆fseek()函数的原型为:
intfseek(FILE*fp,longoffset,intmode)
◆第一个参数fp为文件的指针
◆第二个参数offset指明“想移动的字节数目”
◆第三个参数为mode指明“从何处开始移动”
mode的值可以为:
mode的值
含义
SEEK_SET
从文件的开始处移动
SEEK_CUR
从文件的当前位置移动
SEEK_END
从文件的末尾移动
第二个参数offset的值若为正数,则表示向前移动【注意理解:
向前移动的含义】(例如文件指针当前在第3字节,offset为10,则向前移动10个字节,若mode的值为SEEK_CUR,则文件指针移动到第13个字节;若mode的值为SEEK_SET,则文件指针移动到第10个字节;若mode的值为SEEK_END,则文件指针无法再向后移动,fseek()函数便返回-1,表示移动超出范围而出错);第二个参数offset的值若为负数,则表示向后移动(例如当前在第13字节,offset为10,则向后退步10个字节,若mode的值为SEEK_CUR,文件指针移动到第3个字节;若mode的值为SEEK_END,则文件指针从文件末尾向后退步10个字节。
)
(8)获取文件指针当前的位置的函数:
ftell()
◆ftell()函数的原型为:
size_tftell(FILE*fp)
◆返回值为文件指针当前距离文件起始处的字节数
(9)关闭文件的函数:
fclose()
◆fclose()函数的原型为:
fclose(FILE*fp)
二、文件的两种保存方式
=================================================================
二进制文件:
VI@
#include
intmain()
{
intx=3098;
floaty=3.1415;
FILE*fp;
fp=fopen("data.txt","wb");
if(fp==NULL){
printf("openfileerror.exit.");
return-1;
}
fwrite(&x,sizeof(x),1,fp);
fwrite(&y,sizeof(y),1,fp);
fclose(fp);
fp=fopen("data.txt","rb");
if(fp==NULL){
printf("openfileerror.exit.");
return-1;
}
x=0;y=0.0;
fread(&x,sizeof(x),1,fp);
fread(&y,sizeof(y),1,fp);
printf("x=%d,y=%f\n",x,y);
return0;
}
运行程序后,用记事本打开"data.txt"观察结果。
==================================================================
文本文件:
#include
intmain()
{
intx=3098;
floaty=3.1415;
FILE*fp;
fp=fopen("data.txt","w");
if(fp==NULL){
printf("openfileerror.exit.");
return-1;
}
fprintf(fp,"%d",x);
fprintf(fp,"%f",y);
fclose(fp);
fp=fopen("data.txt","r");
if(fp==NULL){
printf("openfileerror.exit.");
return-1;
}
x=0;y=0.0;
fscanf(fp,"%d",&x);
fscanf(fp,"%f",&y);
printf("x=%d,y=%f\n",x,y);
return0;
}
运行程序后,用记事本打开"data.txt"观察结果。
并思考二进制形式和文本形式存储同样的内容,存放方式有什么不同?
30983.141500
三、矩阵生成和存储的例子
#include
#include
#include
#include
usingnamespacestd;
constintLEN=1024;
int**aMatrix=newint*[LEN];
int**bMatrix=newint*[LEN];
int**cMatrix=newint*[LEN];
voidgen(){
/**函数作用:
创建动态二维数组
函数的返回值:
无
*/
inti,j;
//创建动态二维数组aMatrix
for(i=0;i{
aMatrix[i]=newint[LEN];
}
//创建动态二维数组bMatrix
for(i=0;i{
bMatrix[i]=newint[LEN];
}
//创建动态二维数组cMatrix
for(i=0;i{
cMatrix[i]=newint[LEN];
}
srand((unsignedint)time(NULL));
for(i=0;i{
for(j=0;j{
aMatrix[i][j]=rand();
bMatrix[i][j]=rand();
}
}
}
intsave()
{
/**函数作用:
将生成的矩阵保存到文件中
函数的返回值:
保存成功返回0,失败返回-1
*/
inti,j;
FILE*fp;
fp=fopen("matrix.txt","w");
if(fp==NULL){
printf("openffileerror.\n");
return-1;
}
fprintf(fp,"%d\n",LEN);
for(i=0;i{
for(j=0;j{
fprintf(fp,"%d",aMatrix[i][j]);
}
}
for(i=0;i{
for(j=0;j{
fprintf(fp,"%d",bMatrix[i][j]);
}
}
fclose(fp);
return0;
}
intread()
{
/**函数作用:
将文件中的矩阵读入内存的数组中
函数的返回值:
读取成功返回0,失败返回-1
*/
}
voidcal()
{
/**函数作用:
计算内存中两个矩阵的乘积
函数的返回值:
无
*/
}
intsaveResult()
{
/**函数作用:
将矩阵相乘的结果存放到文件“result.txt”中
函数的返回值:
保存成功返回0,失败返回-1
*/
}
intmain()
{
intret;
gen();
ret=save();
if(ret!
=0){
printf("savefileerror.\n",ret);
getchar();
exit
(1);
}
getchar();
return0;
}
四、复制文件的关键代码
constintLEN=4096;
ret=0;
ret=fread(buf,sizeof(char),LEN,fp1);
while(ret!
=0){
fwrite(buf,sizeof(char),ret,fp2);
ret=fread(buf,sizeof(char),LEN,fp1);
}
注意事项:
(1)fread函数每次最多读取LEN个字节,ret返回真正读取到的字节数,若剩余字节数少于LEN,ret的值就小于LEN。
(2)每次写入的字节数是ret的值
(3)若文件已经完全读取完毕,再次调用fread函数将返回0,即ret的值为0时,表示本次未读到任何数据,因为上次fread就已经读到了文件末尾。
五、扩展阅读
(1)fread()函数的返回值:
fread的作用是按定长记录读取文件,返回的是记录数或者返回0,下面的这段描述更精确。
fread and fwrite returnthenumberofitemssuccessfullyreadorwritten(i.e.,notthenumberof characters). Ifanerroroccurs,ortheend-of-fileisreached,thereturnvalueis a short item count【返回的count比预先要读取的记录数量少】orzero.
若 fread()返回值为0,则要小心。
freaddoesnotdistinguishbetweenend-of-fileanderror,andcallersmustusefeof()andferror() todeterminewhichoccurred.
越过文件末尾或者出现读的错误, fread()均会返回0.
(2)feof()函数判断是否已经越过文件末尾,如果已经越过文件末尾,则返回非0值,否则返回0,
intfeof(FILE*stream);
注意,如果文件长度为100个字符,则读完100个字符后,仍然没有越过文件末尾,feof()的返回值依然是0
只有再向后读一个字符,发现无字符可读,才会设置文件结束符标志位,feof()此时返回非0值,表示已经越过文件末尾。
所以,下面的代码是错误的,在已经读完文件中的最后一个字符后,feof()仍然返回0,因此还会再读一次,其实已经无字符可读。
while(!
feof(fp))//代码错误
{
c=fgetc(fp);
printf("%X\n",c);
}
(3)ferror()函数
在调用各种输入输出函数(如putc.getc.fread.fwrite等)时,如果出现错误,除了函数返回值有所反映外,还可以用ferror函数检查。
它的一般调用形式为ferror(fp);如果ferror返回值为0(假),表示未出错。
如果返回一个非零值,表示出错。
应该注意,对同一个文件每一次调用输入输出函数,均产生一个新的ferror函数值,因此,应当在调用一个输入输出函数后立即检查ferror函数的值,否则信息会丢失。
在执行fopen函数时,ferror函数的初始值自动置为0。
注意,如果读文件已经越过文件末尾,则feof()返回非0值,但不认为是读写错误,因此ferror()函数返回值仍然为0.