文件操作详解(1)

目录

1. 为什么使用文件

2. 什么是文件

2.1 程序文件

2.2 数据文件

2.3 文件名

3. 文件的打开和关闭 

3.1 文件指针

3.2 文件的打开与关闭以及数据的输入输出 

3.3 格式化数据与其他形式数据之间的转换

 4. 通讯录的文件版本(修改)

4.1初始化

4.2数据的加载

4.3数据的保存

1. 为什么使用文件

前面所写的通讯录运行起来的时候,可以给通讯录中增加、删除数 据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯 录程序的时候,数据又得重新录入,无法保存下来,所以我们一般数据持久化的方法有,把数据存放在磁盘文件、存放到数据 库等方式。

使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。

2. 什么是文件

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

2.1 程序文件

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

2.2 数据文件

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

2.3 文件名

一个文件要有一个唯一的文件标识(即文件名),以便用户识别和引用。
文件名包含 3 部分:文件路径 + 文件名主干 + 文件后缀
例如: c:\code\test.txt

3. 文件的打开和关闭 

3.1 文件指针

缓冲文件系统中,关键的概念是 文件类型指针 ,简称 文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE .
FILE* pf;//文件指针变量
定义 pf 是一个指向 FILE 类型数据的指针变量, 通过文件指针变量能够找到与它关联的文件

3.2 文件的打开与关闭以及数据的输入输出 

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

fopen的第一个参数为文件名,第二个参数为使用方式

函数的返回值

 例如:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");//在当前创建的项目的目录中寻找test.txt文件,以读的方式
	if (pf == NULL)//判断文件是否操作成功
	{
		perror("fopen");//文件操作失败的原因
		return 1;
	}
	fclose(pf);//关闭文件
    pf=NULL;
	return 0;
}

运行结果:

 因为没改文件而且以读的方式不会自己创建文件

用fputs写数据

#include<stdio.h>
#include<stdlib.h>
int main()
{
	FILE* pf = fopen("test.txt", "w");//以写的方式操作文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdef", pf);//写入文件
	fclose(pf);
    pf=NULL;
	return 0;
}

 运行结果:

用fgets读数据

#include<stdio.h>
#include<stdlib.h>
int main()
{
	char arr[30] = { 0 };
	FILE* pf = fopen("test.txt", "r");//以读的方式操作文件
	if (pf == NULL)
	{
		perror("fopen");
		exit(0);
	}
	fgets(arr, 29, pf);//将文件里的数据读入数组arr中,最多读取29个
	printf("%s", arr);
	fclose(pf);
    pf=NULL;
	return 0;
}

运行结果:

3.3 格式化数据与其他形式数据之间的转换

  

printf和fprintf之间只差第一个参数,即文件

#include<stdio.h>
struct People
{
	char name[30];
	int number;
	double score;
};

int main()
{
	struct People s = { "zhangsan",20,75.5 };
	FILE* pf = fopen("test.txt", "w");//以写的方式
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fprintf(pf, "%s %d %lf", s.name, s.number, s.score);//将结构体s里的数据存到pf指向的文件中
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}

运行结果:

scanf和fscanf之间只差第一个参数,即文件

#include<stdio.h>
struct People
{
	char name[30];
	int number;
	double score;
};

int main()
{
	struct People s = { 0 };
	FILE* pf = fopen("test.txt", "r");//以读的方式
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	fscanf(pf, "%s %d %lf", s.name, &(s.number), &(s.score));//将pf指向的文件中的数据给s这个结构体
	printf("%s %d %lf", s.name, s.number, s.score);
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}

运行结果:

  

sprintf能够把一个格式化的数据转换为字符串,而sscanf能够把字符串转换为格式化数据

#include<stdio.h>
struct People
{
	char name[30];
	int number;
	double score;
};
int main()
{
	struct People s = { "zhangsan",20,75.5 };
	char buf[100] = { 0 };
	struct People tmp = { 0 };
	sprintf(buf, "%s %d %lf", s.name, s.number, s.score);
	printf("%s\n", buf);//字符串形式打印
	sscanf(buf, "%s %d %lf", tmp.name, &(tmp.number), &(tmp.score));//从buf中提取结构体数据到tmp结构体中
	printf("%s %d %lf", tmp.name, tmp.number, tmp.score);//格式化形式打印
	return 0;
}

运行结果:

 

以上几个函数总结: 

fwrite与fread文件操作函数的使用

#include<stdio.h>
struct People
{
	char name[30];
	int number;
	double score;
};

int main()
{
	struct People s = { "zhangsan",20,75.5 };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fwrite(&s, sizeof(struct People), 1, pf);
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}

 运行结果:

#include<stdio.h>
struct People
{
	char name[30];
	int number;
	double score;
};

int main()
{
	struct People s = { 0 };
	FILE* pf = fopen("test.txt", "rb");//读文件以二进制的方式
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fread(&s, sizeof(struct People), 1, pf);
	printf("%s %d %lf\n", s.name, s.number, s.score);
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}

运行结果:

 4. 通讯录的文件版本(修改)

4.1初始化

//文件版本
void InitContect(Contect* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));
	if (pc->data == NULL)
	{
		perror("InitContect::malloc");
		return;
	}
	memset(pc->data, 0, pc->capacity * sizeof(PeoInfo));
	//加载文件信息到通讯录
	LoadContect(pc);
}

4.2数据的加载

void LoadContect(Contect* pc)
{
	//打开文件
	FILE* pf = fopen("contact.txt", "rb");//以二进制读的形式
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	//读文件
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, pf))//循环结束的标志为文件里数据全部读完
	{
		CheckCapacity(pc);
		pc->data[pc->sz] = tmp;
		pc->sz++;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

4.3数据的保存

void saveContect(const Contect* pc)
{
	FILE* pf = fopen("contact.txt", "wb");//以二进制写的方式打开文件
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	//写文件
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);//将通讯录里的数据保存到文件中
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
}

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山涧晴岚.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值