文件操作(C语言)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

从文件功能上讲可以分为两类:程序文件,数据文件

程序文件:包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)

数据文件:文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

1.1 文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。

文件名包含3部分:文件路径+文件名主干+文件后缀

例如: c:\code\test.txt

2.文件的打开与关闭

2.1 文件指针

文件指针:缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统

声明的,取名FILE.

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

FILE* pf;

定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件

 2.2 文件的打开与关闭

我们在使用文件的时候需要对文件进行打开操作,使用结束后需要及时关闭,这里涉及两个函数:

2.2.1 fopen函数

fopen对文件起着打开的作用

FILE * fopen ( const char * filename, const char * mode );

这里filename对应着相应的文件名

mode表示打开文件的操作方式,如下

返回值:

2.2.2 fclose函数

int fclose ( FILE * stream );这里stream对于着相应的文件指针

(关闭文件后要把文件指针置为空指针)

返回值:

实例展示:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","w");
	int c = 'A';
	if (pf != NULL)
	{
		fputc(c , pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

我们这里进行写入文件操作,由于是用”w"的形式打开文件,这里会自动产生文件,我们这里把字符A写入文件,大家看效果。

3.文件的顺序读写

 3.1 fgetc函数和fputc函数

3.1.1fputc函数

int fputc ( int character, FILE * stream );

将字符写入流,将字符写入流并前进位置指示器。,字符写在流的内部位置指示器指示的位置,然后自动前进一

参数:1.character记录着要写入字符的ASCLL码,要编写的字符的 int 提升。
写入时,该值在内部转换为无符号字符。

2.stream指向标识输出流的 FILE 对象的指针。

返回值:成功后,将返回所写字符。如果发生写入错误,则返回 EOF 并设置错误指示器ferror

3.1.2 fgetc函数

int fgetc ( FILE * stream );

fgetc的作用是将文件的内容读取到内存

参数:stream表示指向标识输入流的 FILE 对象的指针。

返回值:成功后,将返回字符读取(提升为 int 值)。返回类型为 int 以适应特殊值 EOF,该值表示失败:
如果位置指示器位于文件末尾,则该函数返回 EOF 并设置的 eof 指示器 (feof)。
如果发生其他读取错误,该函数还会返回 EOF,但改为设置其错误指示器 (ferror

实例展示:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","w");
	int c = 'A';
	int i = 0;
	if (pf != NULL)
	{
		
		for (i = 0; i < 26; i++)
		{
			fputc(c, pf);
			c++;
		}
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

这里我们给文件进行写入操作:

接下来我们进行读取操作:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","r");//文件以读取的方式打开
	int c = 'A';
	int i = 0;
	if (pf != NULL)
	{
		for (i = 0; i < 26; i++)
		{
			int a = fgetc(pf);
			printf("%c", a);
		}
	
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

结果展示:

3.2 fputs函数和fgets函数 

3.2.1fputs函数

int fputs ( const char * str, FILE * stream );

fputs函数是将 str 指向流的 C 字符串写入流。该函数从指定的地址 (str) 开始复制,直到到达终止空字符 ('\0')。此终止空字符不会复制到流中。

参数:str:包含要写入的内容的 C 字符串

stream:指向标识输出流的 FILE 对象的指针。

返回值:成功时,将返回非负值。
出错时,该函数返回 EOF 并设置错误指示器ferror)。

3.2.2 fgets函数

char * fgets ( char * str, int num, FILE * stream );

fgets函数是从流中读取字符并将其作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符(最后一个位置会给你主动放入\0)或到达换行符或文件末尾,以先发生者为准。(对文件中的字符串一行一行进行处理。) 换行符使 fgets 停止读取,但它被函数视为有效字符,并包含在复制到 str 的字符串中。

参数:str:指向在其中复制字符串读取的字符数组的指针。

num:要复制到 str 的最大字符数(包括终止空字符)。

stream:指向标识输入流的 FILE 对象的指针。 

返回值:成功后,函数返回 str
如果在尝试读取字符时遇到文件末尾,则设置 eof 指示器 (feof)。如果在读取任何字符之前发生这种情况,则返回的指针为空指针(str 的内容保持不变)。
如果发生读取错误,则设置错误指示器ferror),并返回空指针(但str指向的内容可能已更改)。

实例展示:

 文件写入:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","w");//文件以写入的方式打开
	int i = 0;
	if (pf != NULL)
	{
		fputs("hello world",pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}
   

结果展示:

文件读取:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","r");//文件以读取的方式打开
	char arr[20] = { 0 };
	if (pf != NULL)
	{
		 if(fgets(arr,12, pf)!= NULL)
		  puts(arr);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

 结果如下:

3.3 fprintf函数和fscanf函数

3.3.1 fprintf函数

fprintf函数的作用是将格式化数据写入流。

int fprintf ( FILE * stream, const char * format, ... );

参数:stream:指向标识输出流的 FILE 对象的指针。

           format:包含要写入流的文本的 C 字符串。它可以选择性地包含嵌入的格式说明符,这                   些说明符由后续附加参数中指定的值替换,并根据请求设置格式。

返回值:成功后,将返回写入的字符总数。如果发生写入错误,则设置错误指示器ferror)并返回负数。

 3.3.2 fscanf函数

fscanf函数的作用是从流中读取格式化数据

int fscanf ( FILE * stream, const char * format, ... );

参数:stream:指向标识要从中读取数据的输入流的 FILE 对象的指针。

           format:C 字符串,包含一系列字符。

返回值:成功后,该函数返回成功填充的参数列表的项数。此计数可以与预期的项目数匹配,也可以由于匹配失败、读取错误或文件末尾的到达而减少(甚至为零)。如果发生读取错误或在读取时到达文件末尾,则会设置正确的指示器(feof 或 ferror)。并且,如果在成功读取任何数据之前发生任一情况,则返回 EOF

实例展示:

文件写入:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","w");//文件以写入的方式打开
	typedef struct s
	{
		int age;
		char name[20];
	}type;
	type s = { 10,"张三" };
	if (pf != NULL)
	{
		fprintf(pf, "%d %s", s.age, s.name);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}
   

结果展示:

 文件读取:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","r");//文件以读取的方式打开
	typedef struct s
	{
		int age;
		char name[20];
	}type;
	type s ;
	if (pf != NULL)
	{
		fscanf(pf, "%d %s", &s.age, s.name);
	}
	printf("%d %s", s.age, s.name);
	fclose(pf);
	pf = NULL;
	return 0;
}
   

结果展示:

 3.4 fwrite函数和fread函数

3.4.1 fwrite函数

fwrite函数是将数据以二进制的形式写入文件

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

参数:ptr:指向要写入的元素数组的指针,转换为 const void*

          size:要写入的每个元素的大小(以字节为单位)。
          count:元素数,每个元素的大小为字节大小
           stream:指向指定输出流的 FILE 对象的指针。

返回值:返回成功写入的元素总数。如果此数字与 count 参数不同,则写入错误阻止函数完成。在这种情况下,将为设置错误指示器ferror)。如果大小计数为零,则该函数返回零,错误指示器保持不变。

3.4.2 fread函数

fread函数是从中读取计数元素数组,每个元素的大小为字节并将它们存储在 ptr 指定的内存块中。流的位置指示器按读取的总字节数前进。

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

参数:ptr:指向大小至少为 (size*count) 字节的内存块的指针,转换为 void*。

          size:要读取的每个元素的大小(以字节为单位)。

          count:元素数,每个元素的大小为字节大小。

           stream:指向指定输入流的 FILE 对象的指针。

返回值:返回成功读取的元素总数。如果此数字与 count 参数不同,则表示读取时发生读取错误或到达文件末尾。在这两种情况下,都会设置正确的指标,可以分别用 ferror 和 feof 进行检查。
如果大小计数为零,则该函数返回零,并且流状态和 ptr 指向的内容保持不变。

实例展示:

文件写入:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","wb");//文件以二进制的写入的方式打开
	char arr[20] = "张三";
	if (pf != NULL)
	{
		fwrite(arr, 4, sizeof(char), pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

结果展示:

文件读取:

#include <stdio.h>//使用File结构体类型需要包含头文件stdio.h
int main()
{
	FILE* pf = fopen("text.txt","rb");//文件以二进制的读取的方式打开
	char arr[20] = {0};
	if (pf != NULL)
	{
		fread(arr, 4, sizeof(char), pf);
	}
	printf(" % s", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}
   

 结果展示:

 4.文件随机读取

   决定文件读取顺序的是文件指针的位置,而这里我就给大家介绍三个函数,来对文件指针进行操作,以对文件进行随机读取

4.1 fseek函数

 fseek函数的作用是根据文件指针的位置和偏移量来定位文件指针。

  int fseek ( FILE * stream , long int offset , int origin );
参数:

stream:指向标识流的 FILE 对象的指针。

offect: 二进制文件:要从偏移的字节数。
            文本文件:零或 ftell 返回的值。

origin:作偏移参考的位置。它由 <cstdio> 中定义的以下常量之一指定,专门用作此函数的参数:

Constant
Reference position
SEEK_SET文件开头
SEEK_CUR文件指针的当前位置
SEEK_END文件结尾 *

 返回值:如果成功,该函数将返回零。否则,它将返回非零值。如果发生读取或写入错误,则设置错误指示器ferror)。

使用展示:

#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("text.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);//表示从文件开头文件指针到偏移量为9的位置
	fputs(" sam", pFile);
	fclose(pFile);
	return 0;
}

结果展示:

 4.2 ftell

 ftell函数的作用是返回文件指针相对于起始位置的偏移量
   long int ftell ( FILE * stream );
参数:stream:指向标识流的  FILE 对象的指针。
返回值:成功后,返回仓位指标的当前值。失败时,返回 -1L,并将  errno 设置为特定于系统的正值。
使用展示:
#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("text.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	printf("%d", ftell(pFile));
	
	fclose(pFile);
	return 0;
}

结果展示:

 4.3 rewind函数

rewind函数的作用是让文件指针的位置回到文件的起始位置

void rewind ( FILE * stream );

参数:stream:指向标识流的 FILE 对象的指针。

使用展示:

#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("text.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	printf("%d\n", ftell(pFile));
	rewind(pFile);
	printf("%d\n", ftell(pFile));
	fclose(pFile);
	return 0;
}

结果展示:

5.文件读取结束的判定

 5.1 feof函数

 牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。  而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

int feof ( FILE * stream );

参数:指向标识流的 FILE 对象的指针。

返回值:如果设置了与流关联的文件结束指示符,则返回非零值。否则,返回零。

除此之外还有一些返回值能判断文件是否读取结束,如

判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )

例如:

fgetc 判断是否为 EOF .

fgets 判断返回值是否为 NULL .

2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。

例如:

fread判断返回值是否小于实际要读的个数。

6.文件缓冲区

ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半只牛马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值