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


运行截屏:




### C语言文件读取与计算 在C语言中,可以利用标准库函数来完成文件读取并进行相应的数值处理。下面展示一段程序,该程序不仅能够打开指定路径下的文本文件,还能逐字符读入内容,并统计其中特定字符的数量。 #### 使用`getc()`读取文件并计数特定字符实例 对于简单的字符频率分析任务来说,采用循环调用`getc()`的方式非常适合。每次从文件流获取单个字符直到遇到文件结束符EOF为止。在此过程中可以通过条件判断语句增加匹配到的目标字符对应的计数器变量值。 ```c #include <stdio.h> int main(void){ char filename[] = "example.txt"; FILE *filePointer; filePointer = fopen(filename, "r"); if (filePointer == NULL) { printf("无法打开文件。\n"); return 1; } int ch; // 注意这里定义成int而非char以正确处理EOF int countA = 0; while ((ch = getc(filePointer)) != EOF){ if(ch=='a' || ch=='A') ++countA; } fclose(filePointer); printf("'a' 或 'A' 出现次数:%d次\n", countA); return 0; } ``` 此代码片段展示了如何通过`getc()`方法逐一访问文件中的每一个字符,并针对大写或小写字母'a'进行了数量上的累加操作[^1]。 当涉及到更复杂的文件结构或者需要定位到具体位置的数据时,则可能需要用到诸如`fseek()`这样的功能更为强大的I/O控制命令。不过需要注意的是,在文本模式下使用这些函数可能会因为编码转换等原因而导致意外的结果;因此建议尽可能地将其应用于二进制文件的操作场景之中[^2]。 为了适应不同的开发环境和需求变化,还可以调整源码里关于目标文件名的部分,比如替换为宏定义的形式以便于维护: ```c #define TXT_FILE "/path/to/your/file.txt" ... FILE *fp=fopen(TXT_FILE,"r+"); ... ``` 这样做的好处是可以方便地更改工作目录而无需频繁修改多处硬编码字符串常量[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值