带你了解C语言文件的基本操作

引言

我们都知道我们原来链表的那些数据都是存与栈区的,当程序结束后,这些数据全部都会消失,那么我要是想把这些文件保存下来,就是保存到我们的磁盘中,应该如何用处理呢?这时候我们就需要对文件进行操作了,不过我们首先要注意到的就是,磁盘的读取速度太慢了,远远小于我们内存运行的速度,所以我们都是将磁盘的文件一次性的读取到链表中,等程序结束后,把链表的数据在写回到文件中。

ASCII文件和二进制文件的比较:

ASCII文件便于对字符进行逐个处理,也便于输出字符。但一般占存储空间较多,而且要花费转换时间。
二进制文件可以节省外存空间和转换时间,但一个字节并不对应一个字符,不能直接输出字符形式。

文件的处理方法

缓冲文件系统:系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区。用缓冲文件系统进行的输入输出又称为高级磁盘输入输出。
非缓冲文件系统:系统不自动开辟确定大小的缓冲区,而由程序为每个文件设定缓冲区。用非缓冲文件系统进行的输入输出又称为低级输入输出系统。

文件指针

在C语言中有一个特殊的指针,这个指针是已经帮我定义好了的,在stdio的头文件中,定义了一个FILE的文件指针。在缓冲文件系统中,每个被使用的文件都要在内存中开辟一FILE类型的区,存放文件的有关信息。
FILE指针的声明:FILE *fp;这是一个文件指针。变量名是fp,类型是FILE。文件指针指向一个结构,该结构包含以下信息:文件名、文件的当前位置、文件是否正在读或写、是否出错或是否到达文件末尾。

一般对文件的操作有以下的流程

文件操作流程

文件的操作

介绍一下使用文件的方式

使用文件的方式指令的作用
“r”(只读)为输入,打开一个文本文件
“w”(只写)为输出,打开一个文本文件
“a”(追加)向文本,文件尾增加数据
“rb”(只读)为输入,打开一个二进制文件
“wb”(只写)为输出,打开一个二进制文件
“ab”(追加)向二进制文件尾增加数据
"r+“(读写)为读/写打开一个文本文件
"w+”(读写)为读/写建立一个新的文本文件
"w+”(读写)为读/写建立一个新的文本文件
“a+”(读写)为读/写打开一个文本文件(追加)
"rb+“(读写)为读/写打开一个二进制文件
“wb+“(读写)为读/写建立一个新的二进制文件
“ab+”(读写)为读/写打开一个二进制文件
这里我们主要来分析一下“r+”和“w+”(或者“rb+”和“wb+”)的区别:
“r+”(“rb+”):他只能打开存在的文件,存在则打开成功,不存在就会打开失败。
“w+”(“wb+”):这个命令如果文件不存在就会新建一个文件并打开,如果存在那么它会创建一个新的文件同时覆盖之前的文件。

fopen函数

这个函数的函数功能是打开指定的文件。
我们来看看如何调用这个函数:
FILE *fp;
fp=fopen(文件名,使用文件方式);
文件名:就是你要操作的文件,如果直接写文件名的话,那么就是默认在当前目录下打开,如果加路径那么就是在你选择的路径下打开。
使用文件方式,有很多的命令,上面已经介绍。
这个函数是有返回值的,一般打开成功就是返回这个文件指针,如果打开失败会返回NULL。
含有就是文件名和使用文件方式都是字符串。

fclose函数

函数调用:
fclose(文件指针);
函数功能:
使文件指针变量不指向该文件,也就是文件指针变量与文件“脱钩”,此后不能再通过该指针对原来与其相联系的文件进行读写操作
返回值:
关闭成功返回值为0;否则返回EOF(-1)

fwrite函数

函数原型:size_t fwrite(const void *buffer,size_t bytes, sizeo_t n,FILE *fp);
函数参数:buffer-要写入数据的首地址,bytes-每份数据的大小,n-要写入几份数据,fp-要输入的文件指针。
函数返回值:成功时返回写入的单元数,否则返回0
函数功能:fwrite是无格式写函数,用于向文件写入整块的数据。
例如我们把一个用户结构体的数据写入文件

USER user={1001, “admin”,123456}
int pf=0;
pf = fwrite(&user, sizeof(USER), 1, fp);
//fp是已经打开的文件
if(pf==0)
{
	printf(“写入成功!\n”);
}
else
{
	printf(“写入失败!\n”);
}
//这里有一个要注意的地方就是,我们写入成功后,其实这个数据还并没有真正写入到文件
//里面,而是先存在了缓存区,所以我们要刷新一下缓存区使用fflush函数
fflush(pf);

fread函数

函数原型:size_t fread(void *buffer, size_t bytes, sizeo_t n, FILE *fp);
函数参数:buffer-接收数据的首地址,bytes-每份数据的大小,n-要接收几份数据,fp-要操作的文件指针。
函数名返回值:成功时返回读出的单元数,否则返回0
函数功能:fread是无格式读函数,用于向文件读出整块的数据。
例如我们把刚刚的用户读取出来

pf = fread (&user, sizeof(USER), 1, fp);
//fp是已经打开的文件
if(pf==0)
{
	printf(“读取失败!\n”);
}
else
{
	printf(“读取成功!\n”);
}

我们使用读取函数的时候要注意光标的位置,如果光标的位置在末尾那么久读取不到东西,所以为了我们能够读取到数据我们需要一个可以定位光标的函数,下面就有介绍。

rewind函数

函数原型:void rewind(FILE * fp) ;
函数参数:fp-要操作的文件指针
函数返回值:无
函数功能:将文件的光标定位到文件的头部
例子:rewind(pf);

fseek函数

函数原型:int fseek (FILE *fp, long int offset, int origin);
函数参数:fp-要操作的文件指针,offset-偏移量,origin-搜索起始位置
函数返回值:无
函数功能:通过指定相对于开始位置、当前位置或流的末尾位置的偏移量来定位光标位置。
这个函数的第三个参数,只有三个变量,这三个变量是库里面有对应的宏定义,SEEK_SET 或 0(文件开始),SEEK_CUR 或 1(当前文件指针位置),SEEK_END 或 2(文件末尾)。这个偏移量是可正可负的(正向后偏移,负向前偏移),一般如果在文件头那么这个偏移量为正,在尾部则为负,中间就随便了。

ftell函数

函数原型:long int ftell(FILE *pf);
函数参数:pf-要操作的文件
函数返回值:返回字节数
函数功能:获取当前文件指针离文件开头的字节数
例子:

long int nLength=0;
fseek(fp, sizeof(USER),SEEK_END);//偏移到文件尾部
nLength = ftell(fp);//获取当前文件指针离文件开头的字节数
printf(“the file length is %d\n”, nLength);

文件操作和链表综合应用

读取文件

思路分析:我们一般都把数据保存于文件中,那在程序运行的时候我们就需要把这个数据都保存进来,那么我们就需要先定义一个链表(通用链表)的头,然后就是开空间保存数据,在就是从文件中读取数据(读取的数据也需要开空间来保存它,开的空间多大?需要你自己定,所以需要一个参数传进来。),因为我们每次只能保存一个数据,所以我们需要一个循环,来重复这个操作,知道文件被读取完毕。
例程:

LIST *File_read(FILE *fp, int size)
{
	//一个链表头
	LIST *head=NULL;
	void *data=NULL;
	//开辟链表的空间用来保存数据
	head = List_Init();
	data = malloc(size);
	if(data==NULL)
	{
		printf("空间开辟失败");
		return NULL;
	}
	//初始化
	memset(data, '\0', size);
	//开始读取数据
	//移动到文件头
	rewind(fp);
	//然后循环读取数据并开空间保存数据
	while(fread(data, size, 1, fp))
	{
		//数据添加进链表
		List_add(head, data);
		//重新给data开辟空间
		data = malloc(size);
		if(data==NULL)
		{
			printf("空间开辟失败");
			return NULL;
		}
		//初始化
		memset(data, '\0', size);
	}
	return head;
}
//LIST是一个定义好的结构体

向文件添加数据

思路分析:我们先将文件的光标移动到文件末尾,文件移动到末尾用fseek函数,然后在写入数据,写入数据用fwrite函数,最后记得刷新一下。
例程:

void File_add(FILE *fp, void *data, int size)
{
	//移动到文件的末尾
	fseek(fp, 0, SEEK_END);
	//写入数据
	fwrite(data, size, 1, fp);
	//刷新
	fflush(fp);
}

修改文件数据

思路分析:我们要文件的光标移动到头或者末尾都行(建议从头),然后通过偏移找到要修改数据的位置,然后就是重新写入相应大小的数据,最后记得刷新数据区。这里的偏移量要注意记得减一。

void File_Update(FILE *fp, void *data, int size, int index)
{
	if(index!=0)
	{
		//定义到头部,偏移
		fseek(fp, (index-1)*size, SEEK_SET);
		//写入数据
		fwrite(data, size, 1, fp);
		//刷新
		fflush(fp);
	}
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值