【C语言】文件定位读取

本文介绍了C语言中如何进行文件定位读取,包括文件顺序读取和随机读取的概念。重点讲解了fseek函数的使用,如设置文件位置指针以及SEEK_SET、SEEK_CUR、SEEK_END的含义。同时提到了ftell函数用于获取文件位置指针的当前位置。需要注意的是,fseek通常用于二进制文件,但在文本文件操作时需考虑回车换行的特殊处理。

文件定位读取


文件顺序读取

位置指针按字节位置顺序移动。

文件直接读取就是按顺序读取,因为文件内部有位置指针会随着文件的读取或写入而顺序移动。


文件随机读取

读写完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读写文件中任意位置上所需要的字符(字节)。


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
*/


运行截屏:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值