文件操作(基础篇)


思维导图

在这里插入图片描述

文件概念

什么是文件

文件:是指由创建者所定义的一组相关信息的集合。



文件的分类

从编码上来说

  • 文本文件

文本文件:一般指只有字符原生编码构成的二进制计算机文件。

  • 二进制文件

二进制文件:一般指包含ASCII及扩展ASCII字符中编写的数据或程序指令的文件。

  • 广义:在外部存储方式是二进制。
  • 狭义:指除文本文件以外的文件。



一个简单的文件读写

基本步骤

粗略的步骤

  1. 打开文件
  2. 读/写文件
  3. 关闭文件

细化的步骤

  1. 创建FILE文件指针,指向要打开的文件
  2. 调用fopen函数打开文件
  3. 根据需要对文件进行相应的读/写操作
  4. 调用fclose函数关闭文件流


代码演练

实验环境,vs2013

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	
	// 创建文件指针
	FILE *fp;
	// 创建临时存储变量
	int ch;

	// 创建文件路径
	const char *path = "D:\\test.txt";

	// 调用fopen函数打开文件
	fp = fopen(path, "r");

	//读取文件中的内容
	while ((ch = getc(fp)) != EOF)
	{
		putc(ch, stdout);
	}
	
	printf("\n");

	// 关闭文件
	fclose(fp);

	system("pause");
	return 0;
}

上面的这个程序只能说是一个大概的框架,没有添加安全检查。

扫描二维码关注公众号,回复: 8973778 查看本文章

更改后

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	
	// 创建文件指针
	FILE *fp;
	// 创建临时存储变量
	int ch;

	// 创建文件路径
	const char *path = "D:\\test.txt";

	// 调用fopen函数
	// 判断文件是否正常打开
	if ((fp = fopen(path, "r")))
	{
		while ((ch = getc(fp)) != EOF)
		{
			putc(ch,stdout);
		}
		printf("\n");
	}
	else
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	// 判断文件是否正常关闭
	if (fclose(fp) == EOF)
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	system("pause");
	return 0;
}

两次成功运行结果:

在这里插入图片描述

假如删除D盘下的test.txt,看下面的运行结果(请将else中,exit(EXIT_FAILURE);注释掉):

在这里插入图片描述

补充

错误报告函数

void perror(char const *message);

终止函数

void exit(int status);




常用函数

单个字符IO流

getc

从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。

函数原型

int getc(FILE *stream);

参数

  • FILE *stream:这是指向 FILE 对象的指针,该 FILE 对象标识了要在上面执行操作的流。

返回值

该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF



putc

把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。

函数原型

int putc(int char,FILE *stream);

参数

  • int char:要被写入的字符。该字符以其对应的 int 值进行传递。
  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。

返回值

该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误,则返回 EOF。


实例

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	
	// 创建文件指针
	FILE *fp;
	// 创建临时存储变量
	int ch;

	// 创建文件路径
	const char *path = "D:\\test.txt";

	// 调用fopen函数
	// 判断文件是否正常打开
	if ((fp = fopen(path, "r")))
	{
		while ((ch = getc(fp)) != EOF)
		{
			putc(ch,stdout);
		}
		printf("\n");
	}
	else
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	// 判断文件是否正常关闭
	if (fclose(fp) == EOF)
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	system("pause");
	return 0;
}

运行结果

在这里插入图片描述



格式化IO流

fscanf

从流 stream 读取格式化输入。

函数原型

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

参数

  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象标识了流。
  • const char *format: C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符

返回值

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误则返回 EOF。



fprintf

发送格式化输出到流 stream 中。

函数原型

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

参数

  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象标识了流。
  • const char *format: C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符

返回值

如果成功,则返回写入的字符总数,否则返回一个负数


实例

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main()
{
	
	// 创建文件指针
	FILE *fp;
	// 创建临时存储变量
	char ch[21];

	// 创建文件路径
	const char *path = "D:\\test.txt";

	// 调用fopen函数
	// 判断文件是否正常打开
	if ((fp = fopen(path, "r")))
	{
		fscanf(fp,"%s",ch);
		printf("%s",ch);
		printf("\n");
	}
	else
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	// 判断文件是否正常关闭
	if (fclose(fp) == EOF)
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	system("pause");
	return 0;
}

运行结果

在这里插入图片描述



行指针IO流

fgets

从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

函数原型

char *fgets(char *buffer, int buffer_size, FILE *stream );

参数

  • char *buffer:指向一个字符数组的指针,该数组存储了要读取的字符串。
  • int buffer_size:要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
  • FILE *stream:是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。

返回值

如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。如果发生错误,返回一个空指针。



fputs

把字符串写入到指定的流 stream 中,但不包括空字符。

函数原型

char *fputs(char const *buffer, FILE *stream );

参数

  • char const *buffer:这是一个数组,包含了要写入的以空字符终止的字符序列。
  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流。

返回值

该函数返回一个非负值,如果发生错误则返回 EOF


实例

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 81

int main()
{
	
	// 创建文件写入指针
	FILE *input;

	// 创建文件读取指针
	FILE *output;


	// 创建临时存储变量
	char buffer[LEN];

	// 要被写入的内容
	char *pch = "要被写入的内容";

	// 创建文件路径
	const char *path = "D:\\test.txt";

    
	// 调用fopen函数
	// 判断文件是否正常打开
	if ((input = fopen(path, "a+")))
	{
		// 向文件写入内容
		if (fputs(pch, input) != NULL)
		{
			printf("文件写入成功!\n");
		}

	}
	else
	{
		perror(path);
		exit(EXIT_FAILURE);
	}

	// 判断文件是否正常关闭
	if (fclose(input) == EOF)
	{
		perror(path);
		exit(EXIT_FAILURE);
	}




	// 判断文件是否正常打开
	if ((output = fopen(path, "r")))
	{
		// 读取文件中的内容
		while (fgets(buffer,LEN,output))
		{
			puts(buffer);
		}

	}
	else
	{
		perror(path);
		exit(EXIT_FAILURE);
	}



	// 判断文件是否正常关闭
	if (fclose(output) == EOF)
	{
		perror(path);
		exit(EXIT_FAILURE);
	}


	system("pause");
	return 0;
}

运行结果

在这里插入图片描述



二进制IO流

fwrite

buffer 所指向的数组中的数据写入到给定流 stream 中。

函数原型

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

参数

  • void *buffer:指向要被写入的元素数组的指针。
  • size_t size:要被写入的每个元素的大小,以字节为单位。
  • size_t count:元素的个数,每个元素的大小为 size 字节。
  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。

返回值

如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 count参数不同,则会显示一个错误。



fread

从给定流 stream 读取数据到 buffer 所指向的数组中。

函数原型

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

参数

  • void *buffer:这是指向带有最小尺寸 size*count 字节的内存块的指针。
  • size_t size:要读取的每个元素的大小,以字节为单位。
  • size_t count:元素的个数,每个元素的大小为 size 字节。
  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。

返回值

成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 count参数不同,则可能发生了一个错误或者到达了文件末尾。


实例

下面使用这两个函数实现文件的复制功能:

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include<stdio.h>
#include<stdlib.h>

#define BUFFERLEN 16

int main()
{
	
	// 下面的程序,会将1.txt中的内容复制到test.txt中

	// 创建一个文件输入流
	FILE *input;

	// 创建一个文件输出流
	FILE *output;

	// 创建文件路径
	const char *Inpath = "D:\\1.txt";
	const char *Outpath = "D:\\test.txt";

	// 创建缓冲区,缓冲区的大小通常是512字节的整数倍
	char buffer[BUFFERLEN] = {0};

	// 判断源文件是否打开正常
	if (!(input = fopen(Inpath, "r+")))
	{
		perror(Inpath);
		exit(EXIT_FAILURE);
	}


	// 判断源文件是否打开正常
	if (!(output = fopen(Outpath, "r+")))
	{
		perror(Outpath);
		exit(EXIT_FAILURE);
	}


	// 先从源文件中读取数据放入缓冲区
	int res1 = fread(buffer, BUFFERLEN, 1, input);

	// 将缓冲区中的数据复制到目的文件中
	int res2 = fwrite(buffer, BUFFERLEN, 1, output);

	printf("%d\n%d\n", res1,res2);
	

	// 关闭使用的文件流资源
	if (fclose(input) != 0)
		fprintf(stderr, "%s关闭失败!\n", *input);

	if (fclose(output) != 0)
		fprintf(stderr, "%s关闭失败!\n", *output);


	system("pause");
	return 0;
}


随机读取函数

fseek

设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。

函数原型

int fseek(FILE *stream, long int offset, int whence);

参数

  • FLIE *stream:指向 FILE 对象的指针,该 FILE 对象标识了流。
  • long int offset:相对 whence 的偏移量,以字节为单位。
  • int whence:表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:

常量:

  • SEEK_SET:文件的开头

  • SEEK_CUR:文件指针的当前位置

  • SEEK_END:文件的末尾

返回值

如果成功,则该函数返回零,否则返回非零值。



ftell

返回给定流 stream当前文件位置。

函数原型

long int ftell(FILE *stream);

参数

  • FILE *stream:指向 FILE 对象的指针,该 FILE 对象标识了流。

实例

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include<stdio.h>
#include<stdlib.h>

#define BUFFERLEN 1024

int main()
{

	// 创建文件指针
	FILE *fp;
	
	// 创建文件路径
	const char *path = "D:\\test.txt";
	
	// 创建一个中介
	char buffer[BUFFERLEN];

	// 判断文件是否正常打开
	if ((fp = fopen(path, "r+")))
	{
		int res = fseek(fp, 8, SEEK_SET);// 中间的参数:偏移量(相对于后面参数)
		
		if (res != 0)
		{
			fprintf(fp, "随机读取失败!");
		}

		// 从文件中第8个字节处开始读取
		while ((fgets(buffer,BUFFERLEN,fp)))
		{
			fputs(buffer, stdout);
		}

		res = ftell(fp); // 该函数返回现在的位置。
		
		printf("res = %d\n", res);



	}
	else
	{
		perror(path);
		exit(EXIT_FAILURE);

	}


	// 判断文件是否正常关闭
	if ((fclose(fp)) != EOF)
		fprintf(fp, "出错原因:");

	system("pause");
	return 0;
}

运行结果

在这里插入图片描述



错误IO流

emmm,,下面这些函数用来判断流的状态,在《C和指针》书中,对这些函数的描述少之又少,啧啧啧,说实话,笔者也不是很清楚,这些函数的一些细节。常规操作嘛,还是了解一点的。


feof

判断文件是否到达结尾

函数原型:

int feof(FILE *stream);

参数:

  • FILE *stream:这是指向 FILE 对象的指针,该 FILE 对象标识了流。

返回值

当设置了与流关联的文件结束标识符时,该函数返回一个非零值否则返回零。



ferror

测试给定流 stream 的错误标识符。

函数原型:

int ferror(FILE *stream);

参数

  • FILE *stream:这是指向 FILE 对象的指针,该 FILE 对象标识了流。

返回值

如果设置了与流关联的错误标识符,该函数返回一个非零值,否则返回一个零值。



clearerr

函数原型:

void clearerr(FILE *stream);

参数

  • FILE *stream:这是指向 FILE 对象的指针,该 FILE 对象标识了流。

返回值
这不会失败,且不会设置外部变量 errno,**但是如果它检测到它的参数不是一个有效的流,则返回 -1,**并设置 errno 为 EBADF。


实例

#define _CRT_SECURE_NO_WARNINGS// 强行除去安全检查
#include<stdio.h>
#include<stdlib.h>

int main()
{

	// 创建文件指针
	FILE *fp;

	// 创建文件指针
	FILE *fp2;

	// 创建文件路径
	const char *path2 = "test2.txt";
	
	// 创建文件路径
	const char *path = "D:\\1.txt";

	// 创建缓冲区
	char c;
	char c2;


	// 判断文件是否成功打开
	if (!(fp = fopen(path, "r")))
	{
		perror(path);
		exit(EXIT_FAILURE);
	}

	while (1)
	{
		c = getc(fp);
		if (feof(fp))
		{
			break;
		}
		printf("%c", c);
	}
	printf("\n");


	// ferror and clearerror

	// 判断文件是否正常打开
	fp2 = fopen(path2, "w");



	// 获取文件中的内容,此时会报错 
	c2 = getc(fp2);

	if (ferror(fp2))
	{
		printf("1 打开文件失败!\n");
	}

	// 清空错误标识
	clearerr(fp2);

	if (ferror(fp2))
	{
		printf("2 打开文件失败!\n");
	}

	if (fclose(fp2) == EOF)
		printf("文件关闭失败");

	system("pause");
	return 0;
}

运行结果

在这里插入图片描述
小生菜鸟一个,不喜勿喷,如有不足还请兄长们多多指教。

发布了10 篇原创文章 · 获赞 30 · 访问量 1398

猜你喜欢

转载自blog.csdn.net/qq_35502243/article/details/100177487