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所示。

8.4 位置指针对文件的定位 - 图1

所以,在使用该函数进行位置指针定位时需要注意位置指针的起始地址。

返回值:成功则返回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函数来获取文件的长度。