【C语言】文件操作

1. 什么是文件

磁盘上的文件是文件。

但是在程序设计中,一般谈的文件有两种:程序文件和数据文件。

1.1 程序文件

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

1.2 数据文件

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

1.3 文件名

一个文件要有一个唯一的标识,方便用户的识别和引用。

文件名包含三部分:文件路径 + 文件名主干 + 文件名后缀

比如:D:\SteamLibrary\steam.dll

文件标识也常被称为文件名

2. 文件的打开和关闭

打开方式

含义

指定文件不存在时

“r”(只读)

打开一个存在的文本文件

出错

“w”(只写)

打开一个文本文件

建立新文件

“a”(追加)

向文本文件末尾添加数据

建立新文件

“rb”(只读)

打开一个二进制文件

出错

“wb”(只写)

打开一个二进制文件

建立新文件

“ab”(追加)

向二进制文件末尾添加数据

建立新文件

“r+“(读写)

打开一个文本文件

出错

“w+”(读写)

新建一个文本文件

建立新文件

“a+”(读写)

打开一个文件,在文件末尾进行读写

建立新文件

“rb+“(读写)

打开一个二进制文件

出错

“wb+“(读写)

新建一个二进制文件

建立新文件

“ab+”(读写)

打开二进制文件,在文件末尾进行读写

建立新文件

2.1 文件指针

缓冲文件系统中,关键的概念是"文件类型指针",简称"文件指针"。

每个被使用的文件都在内存中开辟了对应一个文件信息区,用来存放文件的相关信息(如文件名字,文件状态,文件所在位置)。这些信息存放在一个结构体变量中,这个结构体类型由系统声明,取名为FILE

VS2022编译环境提供的 stdio.h 头文件有以下申明:

不同C语言编译器下FILE类型包含的内容不完全相同,但是大同小异。

每当打开一个文件,系统会根据文件状态自动创建一个FILE结构的变量,并填充其中的信息。

一般都是创建一个文件指针来维护这个FILE结构的变量,这样更加方便。

下面是一个文件指针的创建:

FILE* pf;

定义 pf 是一个指向FILE类型的指针类型,可以使 pf 指向某个文件的文件信息区。通过该文件信息区中的信息就可以访问该文件,通过文件指针变量就可以找到与它关联的文件

2.2 文件的打开和关闭

文件在读写之前应该先打开文件,使用完毕后应关闭文件

ANSIC 规定打开文件使用 fopen 函数,关闭文件使用 fclose 函数。

在编写程序时,打开文件的同时,会返回一个FILE* 的指针变量指向该文件,相当于建立了文件和指针的关联。

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

//关闭文件
int fclose ( FILE * stream );

打开方式如下:

#include <stdio.h>

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

	return 0;
}

3. 文件的顺序读写

3.1 顺序读写函数介绍

fgetc 和 fputc

int fputc ( int character, FILE * stream );

输出一个字符到 stream 中。

int fgetc ( FILE * stream );

从 stream 中输入一个字符。

int main()
{
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
		return 0;
	int i = 0;
	for (i = 0; i < 26; i++)
	{
		fputc('a' + i, pf); //将26个英文字母按顺序输出到文件
	}
	fclose(pf);
	pf = NULL;
	return 0;
}
int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
		return 0;
	int i = 0;
	char ch = 0;
	for (i = 0; i < 26; i++)
	{
		ch = fgetc(pf);
		printf("%c\n", ch); //按顺序输入数据到屏幕
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

fgets 和 fputs

int fputs ( const char * str, FILE * stream );

输出一个字符串到 stream 中。

char * fgets ( char * str, int num, FILE * stream );

从 stream 中输入(num-1)个字符到 str 所指向的位置。

int main()
{
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
		return 0;
	fputs("hello world", pf); //输出字符串到文件

	fclose(pf);
	pf = NULL;
	return 0;
}
int main()
{
	char s[10];
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
		return 0;
	fgets(s, 10, pf); //将文件中的数据输入到s中存储
	printf("%s\n", s);

	fclose(pf);
	pf = NULL;
	return 0;
}

fscanf 和 fprintf

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

将要输出的数据按照 printf 的格式输出到 stream。

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

按照 scanf 的格式从 stream 中输入数据。

int main()
{
	int a = 100;
	float f = 3.14f;
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
		return 0;
	fprintf(pf, "%d %.2f", a, f); //按照格式将数据输出到pf

	fclose(pf);
	pf = NULL;
	return 0;
}
int main()
{
	int a = 0;
	float f = 0.0f;
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
		return 0;
	fscanf(pf, "%d %f", &a, &f); //按照格式读取文件中的数据
	printf("%d %f", a, f);

	fclose(pf);
	pf = NULL;
	return 0;
}

fread 和 fwrite

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

找到 str 指向的数据,输出 count 个 size 大小的数据到 stream。

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

从 stream 输入 count 个 size 大小的数据到 str 指向的地址。

struct S
{
	int a;
	float f;
	char arr[10];
};

int main()
{
	struct S s = { 100, 3.14f, "hello" };
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
		return 0;
	fwrite(&s, sizeof(struct S), 1, pf);
    //s指向的地址,找到1个sizeof(struct S)大小的数据,输出到pf

	fclose(pf);
	pf = NULL;
	return 0;
}
int main()
{
	struct S s = {0};
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
		return 0;
	fread(&s, sizeof(struct S), 1, pf);
	printf("%d %f %s", s.a, s.f, s.arr);
    //从文件pf中取出1个sizeof(struct S)大小的数据,存放到s的地址

	fclose(pf);
	pf = NULL;
	return 0;
}

4. 文件的随机读写

4.1 fseek

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

根据文件指针的位置和偏移量来定位文件指针。

origin的三个参数:

SEEK_SET

文件开始

SEEK_CUR

文件当前位置

SEEK_END

文件末尾

//此处文本中是26个按顺序排放的英文字母
int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
		return 0;
	fseek(pf, 5, SEEK_SET); //将文本指针重新定位
	char ch = fgetc(pf);
	printf("%c\n", ch);
	

	fclose(pf);
	pf = NULL;
	return 0;
}

4.2 ftell

long int ftell ( FILE * stream );

返回文件指针相对于起始位置的偏移量。

int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
		return 0;
	fseek(pf, -10, SEEK_END);
	printf("%d\n", ftell(pf)); //修改文本指针位置后再打印距离起始位置的偏移量

	fclose(pf);
	pf = NULL;
	return 0;
}

4.3 rewind

void rewind ( FILE * stream );

将文本指针的位置重置到起始位置。

5. 文本文件和二进制文件

根据数据的组织形式,数据文件被称为文本文件二进制文件

数据在内存以二进制形式存储,不加转换输出到外存,就是二进制文件。

如果要求在外存以ASCII形式存储,则需要在存储前进行转换,以ASCII形式存储的文件就是文本文件。

字符一律使用ASCII形式存储,数值型数据既可以使用ASCII形式存储,也可以使用二进制形式存储。

下面是10000在内存中两种存储形式:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值