【C语言】文件操作函数

文件操作函数

  • 1.文件的打开和关闭
    • 1.1fopen
    • 1.2close
  • 2.文件的顺序读写
    • 2.1fgetc和fputc
      • 2.1.1fputc
      • 2.1.2fgetc
    • 2.2fgets和fputs
      • 2.2.1fputs
      • 2.2.2fgets
    • 2.3fscanf和fprintf
      • 2.3.1fprintf
      • 2.3.2fscanf
    • 2.4fread和fwrite
      • 2.4.1fwrite
      • 2.4.2fread
    • 2.5总结
    • 2.6拓展(sscanf和sprintf)
  • 3.文件的随机读写
    • 3.1fseek
    • 3.2ftell
    • 3.3rewind
  • 4.文件读取结束的判定
    • 4.1文件是否结束
    • 4.2feof和ferror


1.文件的打开和关闭

1.1fopen

FILE * fopen ( const char * filename, const char * mode );
  1. fopen的作用是打开文件。
  2. fopen的头文件是,第一个参数是文件名,第二个参数是方式(以什么方式打开文件),打开文件成功,返回指向文件信息区的指针,打开失败返回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
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

结果
【C语言】文件操作函数_第1张图片


2.文件的顺序读写

2.1fgetc和fputc

2.1.1fputc

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

例子
首先创建一个文件。
【C语言】文件操作函数_第2张图片

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;
}

结果
【C语言】文件操作函数_第3张图片

2.1.2fgetc

int fgetc ( FILE * stream );
  1. fgetc的作用是从流中读取字符。fgetc适用于所有输入流(包括stdin和文件等)。
  2. fgetc的头文件是。参数是指向输入流的指针。如果读取成功,返回读取字符的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;
}

结果
【C语言】文件操作函数_第4张图片


2.2fgets和fputs

2.2.1fputs

int fputs (const char * str, FILE * stream);
  1. fputs的作用是将字符串写入流中。fputs适用于所有输出流。
  2. fputs的头文件是。第一个参数是指向要写入流的字符串的指针,第二个参数是指向输出流的指针。如果写入成功就返回一个非负数,失败就返回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;
}

结果
【C语言】文件操作函数_第5张图片

2.2.2fgets

char * fgets ( char * str, int num, FILE * stream );
  1. fgets的作用是从流中读取字符串。fgets适用于所有输入流。
  2. fgets的头文件是。第一次参数是指向一个数组的指针,这个数组用来放从流中读取的字符串,第二个参数是从流中读取的字符个数(实际上是读取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;
}

结果
【C语言】文件操作函数_第6张图片
【C语言】文件操作函数_第7张图片


2.3fscanf和fprintf

2.3.1fprintf

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

例子

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;
}

结果
【C语言】文件操作函数_第8张图片

2.3.2fscanf

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

结果
【C语言】文件操作函数_第9张图片


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的头文件是。第一次参数是指向要写入流的数组的指针,第二个参数是数组元素的大小,第三个参数是数组元素的数目,第四个是指向输出流的指针。如果输出成功则返回写入流的元素总数。如果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;
}

结果
【C语言】文件操作函数_第10张图片

2.4.2fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
  1. fread的作用是从流中读取数据放到内存块中。fread只适用于文件。
  2. fread的头文件是。第一个参数是指向数组的指针,这个数组的大小至少是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;
}

结果
【C语言】文件操作函数_第11张图片

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;
}

结果
【C语言】文件操作函数_第12张图片


3.文件的随机读写

3.1fseek

int fseek ( FILE * stream, long int offset, int origin );
  1. fseek的作用是重新定位流中的位子指示器指向的位置。它是根据文件指针的位置和偏移量来定位文件指针。
  2. 头文件是。第一个参数是指向流的指针,第二个参数是偏移量,第三个参数是起始位置,是偏移量的参考位置,它有固定的三个取值: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;
}

结果
【C语言】文件操作函数_第13张图片

3.2ftell

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

例子

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;
}

结果
【C语言】文件操作函数_第14张图片

3.3rewind

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

例子

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;
}

结果
【C语言】文件操作函数_第15张图片


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);
}

你可能感兴趣的:(c语言)