【C语言】文件操作函数


1.文件的打开和关闭

1.1fopen

FILE * fopen ( const char * filename, const char * mode );
  1. fopen的作用是打开文件。
  2. fopen的头文件是<stdio.h>,第一个参数是文件名,第二个参数是方式(以什么方式打开文件),打开文件成功,返回指向文件信息区的指针,打开失败返回NULL。
  3. 文件的打开方式如下:
文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建立一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

(1)这里的输入和输出是站在内存的角度上的,输入是从文件输入到内存,输出是从内存输出到文件。
(2)什么是文本文件?什么又是二进制文件?
数据在内存中以二进制的形式存储,如果不加转换的输出到外存(文件),就是二进制文件。如果要求在外存(文件)上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
(3)不要看这么多打开方式,在C常用的只有"r"、“w”、"rb"和"wb"这4种。


1.2close

int fclose ( FILE * stream );
  1. fclose的作用是关闭文件。
  2. (1)什么是流(stream)?我认为是数据输入输出的一种介质。将数据输出到屏幕、输出到文件,从文件、键盘输入数据都需要流(stream)的帮助。
    (2)为什么我们平时打印数据、输入数据都不需要流?任何一个C语言程序运行的时候,默认打开三个流:stdin:标准输入流(键盘);stdout:标准输出流(屏幕);stderr:标准错误流(屏幕)。
    (3)所以我们在使用文件输入输出时需要流。我们从文件读写数据,都需要经过流,所以直接从流读写即可。流就是我们的文件指针,类型是FILE*,通过这个流我们可以输入数据到内存,也可以输出数据到文件。
  3. 文件成功关闭就返回0,失败就返回EOF。同时记得把指针置为NULL。

例子

#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述


2.文件的顺序读写

2.1fgetc和fputc

2.1.1fputc

int fputc ( int character, FILE * stream );
  1. fputc的作用是输出字符到流中。fputc适用于所有输出流(包括stdout和文件等)。
  2. fputc的头文件是<stdio.h>。第一个参数是要输入的字符,第二个参数是指向输出流的指针。如果输出成功,返回输出的字符,如果失败返回EOF。

例子
首先创建一个文件。
在这里插入图片描述

int main()
{
	FILE* pf = fopen("test.txt", "w");//我们要写入文件,以写的形式打开
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	int i = 0;
	for (i = 'a'; i <= 'z'; i++)
	{
		fputc(i, pf);//文件里面有指示器,当输入一个字符时,指示器指示下一个位置。
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述

2.1.2fgetc

int fgetc ( FILE * stream );
  1. fgetc的作用是从流中读取字符。fgetc适用于所有输入流(包括stdin和文件等)。
  2. fgetc的头文件是<stdio.h>。参数是指向输入流的指针。如果读取成功,返回读取字符的ASCII码值,如果读取结束或者读取失败就返回EOF。

例子

int main()
{
	FILE* pf = fopen("test.txt", "r");//以读的形式打开文件
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//读取文件
	int ch = 0;
	while (ch = fgetc(pf))//当读取一个字符后,指示器指向下一个字符
	{
		printf("%c ", ch);
		
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述


2.2fgets和fputs

2.2.1fputs

int fputs (const char * str, FILE * stream);
  1. fputs的作用是将字符串写入流中。fputs适用于所有输出流。
  2. fputs的头文件是<stdio.h>。第一个参数是指向要写入流的字符串的指针,第二个参数是指向输出流的指针。如果写入成功就返回一个非负数,失败就返回EOF。
  3. fputs将字符串写入流,遇到’\0’停止,但末尾的’\0’并不会被写入。

例子

int main()
{
	FILE* pf = fopen("test.txt", "w");//以"w"的形式打开,如果先前文件有内容就会被初始化
	if (NULL == pf)
	{
		perror("fopen");
	}
	fputs("hello world\n", pf);
	fputs("welcome", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述

2.2.2fgets

char * fgets ( char * str, int num, FILE * stream );
  1. fgets的作用是从流中读取字符串。fgets适用于所有输入流。
  2. fgets的头文件是<stdio.h>。第一次参数是指向一个数组的指针,这个数组用来放从流中读取的字符串,第二个参数是从流中读取的字符个数(实际上是读取num-1个字符,最后一个字符留给\0),第三个参数是指向输入流的指针。如果读取成功则返回str,读取到文件结束或者读取失败就返回NULL。(读取失败和读取到文件结束该如何区分,后面会讲到)
  3. fgets从流中读取字符串,直到num-1个字符结束,或者读取到换行符结束(换行符也算入num个字符中),或者读取到文件末尾结束。

例子

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	char arr[20] = { 0 };
	fgets(arr, 5, pf);
	printf("%s", arr);
	//fgets(arr, 8, pf);
	//printf("%s", arr);
	return 0;
}

结果
在这里插入图片描述
在这里插入图片描述


2.3fscanf和fprintf

2.3.1fprintf

int fprintf ( FILE * stream, const char * format, ... );
  1. fprintf的作用是将数据格式化输出到流中。fprintf适用于所有输出流。
  2. fprintf的头文件是<stdio.h>。第一个参数是指向输出流的指针,第二个参数是可变参数列表,即可以有多个参数,没有固定。如果输出成功则返回输出的项目数,如果失败就返回负数。

例子

struct Stu
{
	char name[20];
	int age;
	float score;
};
int main()
{
	struct Stu s = { "zhangsan",18,99.5 };
	FILE* pf = fopen("test.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	fprintf(pf, "%s %d %f", s.name, s.age, s.score);
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述

2.3.2fscanf

int fscanf ( FILE * stream, const char * format, ... );
  1. fscanf的作用是从流中格式化地读取数据放到参数列表中的项目。fscanf适用于所有输入流。
  2. fscanf的头文件是<stdio.h>。第一个是指向输入流的指针,第二个参数是可变参数列表。如果读取成功就返回该函数返回参数列表中成功填充的项目数,如果读取失败或者到达文件末尾就返回EOF。

例子

struct Stu
{
	char name[20];
	int age;
	float score;
};
int main()
{
	struct Stu s = { 0 };
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	fscanf(pf, "%s %d %f", s.name, &s.age, &s.score);
	printf("%s %d %f", s.name, s.age, s.score);
	return 0;
}

结果
在这里插入图片描述


2.4fread和fwrite

2.4.1fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
  1. fwrite的作用是将数据块写入流。fwirte只适用于文件。
  2. fwirte的头文件是<stdio.h>。第一次参数是指向要写入流的数组的指针,第二个参数是数组元素的大小,第三个参数是数组元素的数目,第四个是指向输出流的指针。如果输出成功则返回写入流的元素总数。如果size和count都为0 ,则返回0。

例子

struct Stu
{
	char name[20];
	int age;
	float score;
};
int main()
{
	FILE* pf = fopen("test.txt", "wb");//前面的函数读写文件都是文本信息,都可以看懂
	                                   //fread和fwrite读写文件都是二进制信息
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	struct Stu s = { "zhangsan",20,99.5 };
	fwrite(&s, sizeof(struct Stu), 1, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述

2.4.2fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
  1. fread的作用是从流中读取数据放到内存块中。fread只适用于文件。
  2. fread的头文件是<stdio.h>。第一个参数是指向数组的指针,这个数组的大小至少是size*count,这样才能存放从流中读取的数据,第二个参数是数组元素的大小,第三个参数是数组元素的数目,第四个参数是指向输入流的指针。如果读取成功,返回读取元素总数,读取失败或者读取到文件末尾,都设置了各自的指示符,这些指示符可以与feror和feof搭配使用,从而得出是读取是失败还是读取到文件末尾(后面会讲到),如果count或者size是0,则返回0。

例子

struct Stu
{
	char name[20];
	int age;
	float score;
};
int main()
{
	FILE* pf = fopen("test.txt", "rb");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	struct Stu s = { 0 };
	fread(&s, sizeof(struct Stu), 1, pf);
	printf("%s %d %f", s.name, s.age, s.score);
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述

2.5总结

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

2.6拓展(sscanf和sprintf)

  1. scanf从键盘读取格式化的数据(输入流:键盘stdin),printf把数据输出到屏幕上(输出流:屏幕stdout)。
  2. fscanf针对所有输入流的格式化的输入(输入流:stdin,打开的文件),fprintf针对所有输出流的格式化的输出(输出流:stdout、打开的文件)。
  3. sscanf从一个字符串中还原出一个格式化的数据,sprintf把格式化的数据存放在一个字符串。

例子

struct Stu
{
	char name[20];
	int age;
	float score;
};
int main()
{
	struct Stu s = { "zhangsan",18,99.5 };
	char buf[100] = { 0 };
	sprintf(buf, "%s %d %f", s.name, s.age, s.score);
	printf("%s\n", buf);
	printf("-------分割线---------\n");
	struct Stu tmp = { 0 };
	sscanf(buf, "%s %d %f", tmp.name, &tmp.age, &tmp.score);
	printf("%s %d %f", tmp.name, tmp.age, tmp.score);
	return 0;
}

结果
在这里插入图片描述


3.文件的随机读写

3.1fseek

int fseek ( FILE * stream, long int offset, int origin );
  1. fseek的作用是重新定位流中的位子指示器指向的位置。它是根据文件指针的位置和偏移量来定位文件指针。
  2. 头文件是<stdio.h>。第一个参数是指向流的指针,第二个参数是偏移量,第三个参数是起始位置,是偏移量的参考位置,它有固定的三个取值:SEEK_SET(文件开头)、SEEK_CUR(文件指针当前位置)、SEEK_END(文件末尾)。如果成功返回零,失败返回非零值。

例子

int main()
{
	FILE* pf = fopen("test.txt", "r");//先在文件内写好abcdef,现在用读的形式打开
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//文件的顺序读写,读完一个字符后,文件指针指向下一个字符
	printf("%c\n", fgetc(pf));//a
	printf("%c\n", fgetc(pf));//b
	printf("%c\n", fgetc(pf));//c
	//按照顺序读写,接下来打印的是d,但我想要打印b
	fseek(pf, -2, SEEK_CUR);//当前位置是文件指针(位置指示器)指向d,后前偏移2就指向b
	printf("%c\n", fgetc(pf));
	//法2:	fseek(pf,1,SEEK_SET);从开头开始偏移
	//		printf("%c\n",fgetc(pf));
	//法3:	fseek(pf,-4,SEEK_END);//从末尾开始偏移
	//		printf("%c\n", fgetc(pf));
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
在这里插入图片描述

3.2ftell

long int ftell ( FILE * stream );
  1. ftell的作用是返回文件指针相对于起始位置的偏移量。
  2. 头文件是<stdio.h>,参数是指向流的指针,返回值是当前文件指针相对于起始位置的偏移量。

例子

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	printf("%c\n", fgetc(pf));//a
	printf("%c\n", fgetc(pf));//b
	printf("%d\n", ftell(pf));
	return 0;
}

结果
在这里插入图片描述

3.3rewind

void rewind ( FILE * stream );
  1. rewind的作用是让文件指针的位置回到文件的起始位置。
  2. 头文件是<stdio.h>,参数是指向流的指针,无返回值。

例子

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	printf("%c\n", fgetc(pf));//a
	printf("%c\n", fgetc(pf));//b
	printf("%d\n", ftell(pf));//2
	rewind(pf);
	printf("%c\n", fgetc(pf));//a
	return 0;
}

结果
在这里插入图片描述


4.文件读取结束的判定

4.1文件是否结束

  1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
    例如:
    fgetc 判断是否为 EOF
    fgets 判断返回值是否为 NULL
  2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
    例如:
    fread判断返回值是否小于实际要读的个数

4.2feof和ferror

  1. 在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。
    而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
  2. feof返回真,说明是文件正常读取遇到了结束标志而结束的。
  3. ferror返回真,说明文件在读取过程中出错了,结束的。

例子

int main(void)
{
  int c; // 注意:int,非char,要求处理EOF
  FILE* fp = fopen("test.txt", "r");
  if(!fp) {
    perror("File opening failed");
    return EXIT_FAILURE;
 }
//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
  while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
 {         
   putchar(c);
 }
 //判断是什么原因结束的
  if (ferror(fp))
    puts("I/O error when reading");
  else if (feof(fp))
    puts("End of file reached successfully");
  fclose(fp);
}

  • 10
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值