C 语言文件操作

        相信很多初学 C 语言的老铁,看到 C 语言文件的时候,对其中所用到的函数概念会比较模糊,本篇文章将会对其进行解答与演示。

注:本文所有用到的库函数(fgetc、fopen、fclose等……函数参数的细节等都能在下面的网站链接所找到)

本文所用到的全部代码:C 语言文件操作

本文所用到的网站链接:C 语言cplusplus


目录

文件

文件名

文件指针

文件的关闭与打开

文件顺序的读写

fgetc 和 fputc

fgets 和 fputs

fscanf 和 fprintf

fread 和 fwrite

文件的随机读写 

fseek

ftell

rewind

后语


文件

磁盘上的文件是文件。
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

  1. 程序文件:包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。
  2. 数据文件:文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
例如:D:\Code\blog.c
为了方便起见,文件标识常被称为文件名。


文件指针

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

//例如,VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:
struct _iobuf {
     char *_ptr;       //文件输入的下一个位置。     
        int   _cnt;        //当前缓冲区的相对位置。
        char *_base;       //指针的基础位置(即是文件的起始位置)。
        int   _flag;       //文件标志。
        int   _file;       //文件的有效性验证。
        int   _charbuf;    //检查缓冲区状况,如果无缓冲区则不读取。
        int   _bufsiz;     //缓冲区的大小。
        char *_tmpfname;    //临时文件名。
        };
typedef struct _iobuf FILE;

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

下面我们可以创建一个FILE*的指针变量:

FILE* pf;

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

文件的关闭与打开

之前有一个故事说:“把大象装进冰箱总共分几步?” 

  1. 把冰箱门先打开
  2. 把大象塞进去
  3. 关闭冰箱门

        文件的操作也跟其步骤类似,我们先要把文件的“门”打开,在文件里面做完操作之后要把文件的“门”关闭上。

在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
ANSIC 规定使用 fopen 函数来打开文件,fclose 函数 来关闭文件。

//打开
FILE * fopen ( const char * filename, const char * mode );

文件使用方式 含义 如果指定文件不存在
“r”(只读) 为了输入数据,打开一个已经存在的文本文件 出错
“w”(只写) 为了输出数据,打开一个文本文件 建立一个新的文件
“a”(追加) 向文本文件尾添加数据 建立一个新的文件
“rb”(只读) 为了输入数据,打开一个二进制文件 出错
“wb”(只写) 为了输出数据,打开一个二进制文件 建立一个新的文件
“ab”(追加) 向一个二进制文件尾添加数据 出错
“r+”(读写) 为了读和写,打开一个文本文件 出错
“w+”(读写) 为了读和写,建议一个新的文件 建立一个新的文件
“a+”(读写) 打开一个文件,在文件尾进行读写 建立一个新的文件
“rb+”(读写) 为了读和写打开一个二进制文件 出错
“wb+”(读写) 为了读和写,新建一个新的二进制文件 建立一个新的文件
“ab+”(读写) 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件
//关闭
int fclose ( FILE * stream );

代码演示: 

int main()
{
	FILE* pf = fopen("file.txt", "w");
	
	if (pf != NULL)
	{

		//文件操作
		//………………

		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

注:pf = NULL 的原因:

通过在对代码的运行我门在项目文件里面发现了所创建的 txt 文件

文件顺序的读写

fgetc 和 fputc

fputc 字符输入函数

int main()
{
	FILE* pf = fopen("file.txt", "w");

	if (pf != NULL)
	{

		//写文件
		char ch = 0;
		for (ch = 'a'; ch <= 'z'; ch++)
		{
			fputc(ch , pf);
			fputc(' ', pf);
		}


		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

通过在对代码的运行我门在项目文件里面发现所创建的 txt 文件 里面有了 a - z 的字母

fgetc 字符输出函数

int main()
{
	FILE* pf = fopen("file.txt", "r");

	if (pf != NULL)
	{

		//读文件
		char ch = 0;
		while ((ch = fgetc(pf)) != EOF)
		{
			printf("%c", ch);
		}

		//ch = fgetc(pf);
		//printf("%c", ch);//a

		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

fgets 和 fputs

fputs 文本输入函数

int main()
{
	FILE* pf = fopen("file.txt", "w");

	if (pf != NULL)
	{

		//写文件
		fputs("hunter ", pf);

		char str[] = "yyds";
		fputs(str, pf);

		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

fgets 文本输出函数

int main()
{
	FILE* pf = fopen("file.txt", "r");

	if (pf != NULL)
	{

		//读文件
		char arr[100] = { 0 };
		fgets(arr, 100, pf);
		printf("%s", arr);
		

		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

注:读取 n-1个字符 ,所以如果上述代码 我只想读取 h 字符的话,在上述图片的部分应该写 2 

fscanf 和 fprintf

fprintf 格式化输出函数

int main()
{
	struct hunter yyds = { "hunteryyds",20,1.88 };

	FILE* pf = fopen("file.txt", "w");
	if (pf != NULL)
	{
		
		//写文件
		fprintf(pf, "你的姓名:%s\n你的年龄:%d\n你的身高:%.2lf\n", yyds.a, yyds.b, yyds.c);

		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

fscanf 格式化输入函数

struct hunter
{
	char a[20];
	int b;
	double c;
};

int main()
{
	struct hunter yyds = { 0 };
	FILE* pf = fopen("file.txt", "r");
	if (pf != NULL)
	{

		//读文件
		fscanf(pf, "%s%d%.2lf", &(yyds.a), &(yyds.b), &(yyds.c));
		printf("%s %d %.2lf", yyds.a, yyds.b, yyds.c);

		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

fread 和 fwrite

fwrite 二进制输出

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	FILE* pf = fopen("file.txt", "wb");
	if (pf != NULL)
	{

		//二进制写文件
		fwrite(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);

		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

注:如果各位想进一步看清的话:

fread 二进制输入

int main()
{
	int arr[10] = { 0 };
	FILE* pf = fopen("file.txt", "rb");
	if (pf != NULL)
	{

		//读文件
		fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);

		for (int i = 0; i < 10; i++)
		{
			printf("%d ", arr[i]);
		}

		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

文件的随机读写 

fseek

offset: 

  • 二进制文件:要从原点偏移的字节数。
  • 文本文件:要么为零,要么为ftell返回的值。

origin:

ConstantReference position
SEEK_SET文件开始
SEEK_CUR文件指针的当前位置
SEEK_END文件结束

int main()
{
	FILE* pf = fopen("file.txt", "w");

	if (pf != NULL)
	{

		
		fputs("hunter    yyds", pf);

		fseek(pf, 7, SEEK_SET);

		fputs("NB", pf);

		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

ftell

看光标所处位置。

int main()
{
	FILE* pf = fopen("file.txt", "r");

	if (pf != NULL)
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);//h

		ch = fgetc(pf);
		printf("%c\n", ch);//u

		ch = fgetc(pf);
		printf("%c\n", ch);//n

		ch = fgetc(pf);
		printf("%c\n", ch);//t

		int pos = ftell(pf);
		printf("pos = %d\n", pos);

		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}

rewind

回到起始位置。

int main()
{
	FILE* pf = fopen("file.txt", "r");

	if (pf != NULL)
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);//h

		ch = fgetc(pf);
		printf("%c\n", ch);//u

		ch = fgetc(pf);
		printf("%c\n", ch);//n

		ch = fgetc(pf);
		printf("%c\n", ch);//t

		int pos = ftell(pf);
		printf("pos = %d\n", pos);

		rewind(pf);
		pos = ftell(pf);
		printf("pos = %d\n", pos);

		//文件关闭
		fclose(pf);
		pf = NULL;//防止野指针
	}
	return 0;
}


后语

希望各位在翻阅过本篇文章各位能够对 C 语言文件操作有更加深刻的印象。

希望能对各位有所帮助,如果各位有任何疑问,欢迎各位留言,我们可以进行友好的探讨与交流。

欢乐的时间总是过得特别快。又到时间讲bye,我们下一篇再见!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值