8.4 位置指针对文件的定位
在讲解位置指针之前,先要明白的是位置指针和前面所讲的文件指针并不相同。文件指针指向所要操作的文件,而位置指针指向读写文件内部存储数据的地址,通过移动位置指针可以在文件的指定位置上进行数据的读写操作。
对位置指针的操作通常用以下3个函数来实现。
1.rewind函数
void rewind(FILE*fp);
功能:将位置指针重新定位到文件的开头。
返回值:无。
下面通过一段代码来看看该函数的使用,其功能为对打开的文件进行两次备份操作。
include<stdio.h>
int main()
{
FILEfpin,fpout1,*fpout2;
fpin=fopen("text1.txt","r");
fpout1=fopen("text2.txt","w");
fpout2=fopen("text3.txt","w");
if(NULL==fpin||NULL==fpout1||NULL==fpout2)
{
printf("打开失败!\n");
return 0;
}
while(!feof(fpin))
fputc(fgetc(fpin),fpout1);
rewind(fpin);
while(!feof(fpin))
fputc(fgetc(fpin),fpout2);
fclose(fpin);
fclose(fpout1);
fclose(fpout2);
return 0;
}
在上面的代码中,先打开text1.txt,将其中的内容读取出来并写入到text2.txt中,这时文件中的位置指针已经不再指向文件中数据的起始地址,所以再次读取text1.txt之前,要先采用rewind函数将其位置指针重新定位到文件的起始地址,再次将其中的数据备份到text2.txt中。
2.fseek函数
int fseek(FILE*fp,long offset,int fromwhere);
功能:按照需要任意移动位置指针,其中,参数fp是所要操作的文件指针,参数offset是以fromwhere参数为起始位置的偏移量,而参数fromwhere的取值如表8-2所示。
所以,在使用该函数进行位置指针定位时需要注意位置指针的起始地址。
返回值:成功则返回0,否则返回非0值。
接下来通过代码了解该函数的使用。以下代码的功能为先通过fwrite函数将信息写入指定的文件中,然后通过fseek函数来进行位置指针的定位,逐一取出其中的数据信息存放到指定的数组中。
include<stdio.h>
define N 4
struct stu
{
char name[10];
char nu[10];
int score;
}st[N]={{"李小鹏","21009011",326},
{"张迪蝶","21009012",562},
{"彭晓敏","21009013",456},
{"王梅梅","21009014",258}
};
int main()
{
FILEfpin,fpout;
fpin=fopen("bina.txt","w");
if(NULL==fpin)
{
printf("打开失败!\n");
return 0;
}
fwrite(&st,sizeof(struct stu),4,fpin);
fclose(fpin);
fpout=fopen("bina.txt","r");
if(NULL==fpout)
{
printf("打开失败!\n");
return 0;
}
struct stu sd[N];
int i;
for(i=0;i<N;i++)
{
fseek(fpout,-sizeof(sd[i])*(i+1),2);
fread(&sd[i],sizeof(sd[i]),1,fpout);
printf("%s\t%s\t%d\n",sd[i].name,sd[i].nu,sd[i].score);
}
fclose(fpout);
return 0;
}
运行结果:
王梅梅21009014 258
彭晓敏21009013 456
张迪蝶21009012 562
李小鹏21009011 326
在上面的代码中,在使用fseek函数的时候将fromwhere起始地址设置为2,所以位置指针的相对位置是相对于文件的末端开始的,fseek函数中的第二个参数是一个负值,这样就将文件中的数据一一存放到指定的数组中,并且进行打印输出。
3.ftell函数
long ftell(FILE*fp);
功能:获取位置指针当前位置相对于文件首的偏移字节数。
返回值:调用成功则返回当前文件的读写位置,失败则返回-1。
接下来通过一个简单的代码来了解该函数的使用。以下代码的功能为通过ftell函数获取每个学生信息存储地址相对于文件首的偏移字节数。
include<stdio.h>
define N 4
struct stu
{
char name[10];
char nu[10];
int score;
}st[N]={{"李小鹏","21009011",326},
{"张迪蝶","21009012",562},
{"彭晓敏","21009013",456},
{"王梅梅","21009014",258}
};
int main()
{
FILEfpin,fpout;
fpin=fopen("bina.txt","w");
if(NULL==fpin)
{
printf("打开失败!\n");
return 0;
}
fwrite(&st,sizeof(struct stu),4,fpin);
fclose(fpin);
fpout=fopen("bina.txt","r");
if(NULL==fpout)
{
printf("打开失败!\n");
return 0;
}
struct stu sd[N];
int i;
for(i=0;i<N;i++)
{
printf("%d\t",ftell(fpout));
fread(&sd[i],sizeof(sd[i]),1,fpout);
}
return 0;
}
运行结果:
0 24 48 72
从上面的运行结果可以看出,每个学生信息在内存中占用的字节大小为24字节。结合上面讲解的fseek函数,可以取文件的长度,代码如下:
include<stdio.h>
define N 4
struct stu
{
char name[10];
char nu[10];
int score;
}st[N]={{"李小鹏","21009011",326},
{"张迪蝶","21009012",562},
{"彭晓敏","21009013",456},
{"王梅梅","21009014",258}
};
int main()
{
FILEfpin,fpout;
fpin=fopen("bina.txt","w");
if(NULL==fpin)
{
printf("打开失败!\n");
return 0;
}
fwrite(&st,sizeof(struct stu),4,fpin);
fclose(fpin);
fpout=fopen("bina.txt","r");
if(NULL==fpout)
{
printf("打开失败!\n");
return 0;
}
fseek(fpout,0,2);
printf("bian.txt文件占用的内存大小为%d字节\n",ftell(fpout));
return 0;
}
运行结果:
bian.txt文件占用的内存大小为96字节
从上面的运行结果可以看出,bian.txt文件占用96字节。由上面的代码可知,每个学生信息在内存中占用24字节的大小,总共有4个学生,即96字节,所以不仅可以通过fseek函数来随机指定位置指针,还可以通过fseek函数和ftell函数来获取文件的长度。