文件定位读取
文件顺序读取
位置指针按字节位置顺序移动。
文件直接读取就是按顺序读取,因为文件内部有位置指针会随着文件的读取或写入而顺序移动。
文件随机读取
读写完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读写文件中任意位置上所需要的字符(字节)。
fseek函数
头文件:stdio.h
功 能:以fromwhere为基准(好像数组的基地址一样)以offset为偏移量(下标)来设置fp文件位置指针的位置。
用 法:int fseek(FILE *fp,longoffset, int fromwhere);
返回值:成功,返回0;失败,返回-1.
参数说明:
第二个参数为负则向
第三个参数可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END依次为0,1和2.
举 例:
—fseek(fp,100L,0);
将文件位置指针移到离文件头100个字节处。
—fseek(fp,50L,1);
将文件位置指针移到离当前位置50个字节处。
—fseek(fp,-50L,2);
将文件位置指针向前移到离文件尾50个字节处。
注 意:文件的位置指针和文件指针是不一样的。如果文件指针不被重置是不会改变的,也可以理解一个文件就一个地址用指针来指向,而文件位置指针会随着顺序读取或写入而顺序移动位置。
更多详细内容:http://blog.youkuaiyun.com/chenglibin1988/article/details/8750906
PS:fseek函数一般用于二进制文件,也可以用于文本文件。用于文本文件操作时,需特别注意回车换行的情况:因为在一般浏览工具如UltraEdit中,回车换行视为两个字符0x0D和0x0A,但真实的文件读写和定位时却按照一个字符0x0A进行处理,因此碰到此类问题时,可以考虑将文件整个读入内存,然后在内存中手工插入0x0D的方法,这样可以达到较好的处理效果。
示 例:
#include <stdio.h>
#define SIZE 5
#define NAM_SIZE 10
#define NUM_SIZE 10
#define TEL_SIZE 12
char filename[50];
struct student
{
char name[NAM_SIZE];
char num[NUM_SIZE];
int age;
char tel[TEL_SIZE];
}stu[SIZE],st;
bool save();
int main()
{
FILE *fp;
int pos=1;
if(save())
{
if(!(fp=fopen(filename,"rb+")))
{
printf("Can't open %s",filename);
return -1;
}
fseek(fp,pos*sizeof(student),0);
if(fread(&st,sizeof(student),1,fp)==1)
{
printf("name\tnum\tage\t tel\n");
printf("%s\t%s\t%1d\t%s\n",st.name,st.num,st.age,st.tel);
}
else
return -1;
fseek(fp,pos*sizeof(student),1);
if(fread(&st,sizeof(student),1,fp)==1)
{
printf("name\tnum\tage\t tel\n");
printf("%s\t%s\t%1d\t%s\n",st.name,st.num,st.age,st.tel);
}
else
return -1;
fseek(fp,-pos*sizeof(student),2);
if(fread(&st,sizeof(student),1,fp)==1)
{
printf("name\tnum\tage\t tel\n");
printf("%s\t%s\t%1d\t%s\n",st.name,st.num,st.age,st.tel);
}
else
return -1;
}
else
{
printf("存储错误!!!\n");
return -1;
}
return 0;
}
bool save()
{
FILE *fp;
int i;
printf("Please input %d students's name num age and telephone:\n",SIZE);
for(i=0;i<SIZE;i++)
scanf("%s %s %d %s",&stu[i].name,&stu[i].num,&stu[i].age,&stu[i].tel);
printf("Please input your filename:");
scanf("%s",filename);
if(!(fp=fopen(filename,"wb")))
{
printf("Can not open %s\n",filename);
return false;
}
for(i=0;i<SIZE;i++)
if(fwrite(&stu[i],sizeof(student),1,fp)!=1)
printf("文件写入失败!\n");
fclose(fp);
return true;
}
/*
Alice 001 18 15171162354
Bob 002 18 15171162355
Cindy 003 18 15171162356
Dalin 004 18 15171162357
Ela 005 18 15171162358
*/
运行截屏:
ftell函数(与fseek函数配套使用)
头文件:stdio.h
功 能:得到文件位置指针当前位置相对于文件首的偏移字节数。
用 法:long ftell(FILE *stream);
返回值:成功,返回偏移字节数;错误,返回-1.
补充:因为ftell返回long型,根据long型的取值范围-231~231-1(-2147483648~2147483647),故对大于2.1G的文件进行操作时出错。
示例:
#include <stdio.h>
#define SIZE 5
#define NAM_SIZE 10
#define NUM_SIZE 10
#define TEL_SIZE 12
char filename[50];
struct student
{
char name[NAM_SIZE];
char num[NUM_SIZE];
int age;
char tel[TEL_SIZE];
}stu[SIZE],st;
bool save();
int main()
{
FILE *fp;
long len;
int pos=1;
if(save())
{
if(!(fp=fopen(filename,"rb+")))
{
printf("Can't open %s",filename);
return -1;
}
len=ftell(fp);
printf("The position pointer is at %lld byte(s)\n",len);
fseek(fp,sizeof(student),0);
len=ftell(fp);
printf("The position pointer is at %lld byte(s)\n",len);
}
else
{
printf("存储错误!!!\n");
return -1;
}
return 0;
}
bool save()
{
FILE *fp;
int i;
printf("Please input %d students's name num age and telephone:\n",SIZE);
for(i=0;i<SIZE;i++)
scanf("%s %s %d %s",&stu[i].name,&stu[i].num,&stu[i].age,&stu[i].tel);
printf("Please input your filename:");
scanf("%s",filename);
if(!(fp=fopen(filename,"wb")))
{
printf("Can not open %s\n",filename);
return false;
}
for(i=0;i<SIZE;i++)
if(fwrite(&stu[i],sizeof(student),1,fp)!=1)
printf("文件写入失败!\n");
fclose(fp);
return true;
}
/*
Alice 001 18 15171162354
Bob 002 18 15171162355
Cindy 003 18 15171162356
Dalin 004 18 15171162357
Ela 005 18 15171162358
*/
运行截屏: