从零开始的C语言:文件操作与数据存储(上)(文件的分类,文件的打开和关闭)

2025博客之星年度评选已开启 10w+人浏览 1.6k人参与

文件操作与数据存储

  1. 为什么使⽤⽂件?
    如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件。

  2. 什么是⽂件?
    磁盘(硬盘)上的⽂件是⽂件。
    但是在程序设计中,我们⼀般谈的⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类的)。

程序文件

程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows环境后缀为.exe)。

数据文件

⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。

流和标准流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。

C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。
⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。

标准流

那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?
那是因为C语⾔程序在启动的时候,默认打开了3个流:

• stdin -

标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。

stdout

标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。

• stderr

标准错误流,⼤多数环境中输出到显⽰器界⾯。
这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。
stdin、stdout、stderr 三个流的类型是: FILE *
通常称为⽂件指针。
C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作。

⽂件指针

缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系
统声明的,取名 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;

文件的打开和关闭

fopen

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

⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。
在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了指针和⽂件的关系。
ASIIC 规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件。

mode表⽰⽂件的打开模式,下⾯都是⽂件的打开模式:

“r”
只读打开文件 文件必须存在,否则fopen返回NULL 只能读取文件内容,不能写入 / 修改

“w”
只写创建 / 截断文件 文件不存在则创建;存在则清空(截断)内容 打开后文件指针指向开头,写入会覆盖原有内容

“a”
追加写打开 / 创建文件 文件不存在则创建;存在则保留原有内容 写入内容始终追加到文件末尾,文件指针指向末尾

“r+”
读写打开文件 文件必须存在,否则fopen返回NULL 可同时读写,文件指针初始指向开头

“w+”
读写创建 / 截断文件 文件不存在则创建;存在则清空内容 可同时读写,初始指针指向开头

“a+”
读写打开 / 创建文件(追加读 + 写) 文件不存在则创建;存在则保留原有内容 写入始终追加到末尾;读取可从开头开始

fclose

在这里插入图片描述
fclose为关闭文件参数为流的指向的空间

#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt","r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	int fclose(pf);
	pf = NULL;
	return 0;
}

在这个代码中text.txt 文件不存在。所以只能返回空指针,用perror标记错误

在这里插入图片描述

文件的读写

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述函数的原型如上;
读写的函数有很多,我们选几个来讲一下他们的基础用法
在这里插入图片描述

fgetc

fgetc int fgetc(FILE *stream)

参数为流指向的文件
首先建立一个文本文件

text.txt
在这里插入图片描述
在这里插入图片描述
用vs打开
在这里插入图片描述

在这里插入图片描述
代码如下


int main()
{
	FILE* pf = fopen("test.txt","r");
	if (pf==NULL)//防止为空指针,提前结束
	{
		perror("fopen");
		return 1;//终止
	}
	int c = 0;
	while ((c=fgetc(pf))!=EOF)//语法格式
	{
		printf("%c", c);
	}

	fclose(pf);//关闭文件
	pf = NULL;//置为空指针
	return 0;
}

在这里插入图片描述

fputc和fputs

fputs输出字符串
fputc输出单个字符
在这里插入图片描述
fputs读取字符串

int main()
{
	FILE* pr = fopen("test.txt","w");
	if (pr==NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("hello world",pr);
	fclose(pr);
	pr = NULL;
	return 0;
}

在这里插入图片描述

scanf fscanf scanf

printf fprintf sprintf辨析

scanf/printf:面向标准输入 / 输出流(键盘 / 屏幕);
fscanf/fprintf:面向文件流;
sscanf/sprintf:面向内存字符串。

scanf	int scanf(const char *format, ...);	标准输入(键盘)	从键盘按格式读取数据到变量	直接读取用户输入
fscanf	int fscanf(FILE *stream, const char *format, ...);	文件流	从指定文件按格式读取数据到变量	读取文件中的格式化数据
sscanf	int sscanf(const char *str, const char *format, ...);	内存字符串	从指定字符串按格式解析数据到变量	解析字符串中的结构化数据

在这里插入图片描述

int main()
{
	int a = 0;
	/*printf("%s","hello world\n");
	fprintf(stdout, "%s", "hello world\n");*/
	/*scanf("%d",&a);*/
	fscanf(stdin,"%d",&a);
	printf("%d",a);
	system("pause");return 0;
}

文件的随机读写

fseek

根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。

int fseek ( FILE * stream, long int offset, int origin )
在这里插入图片描述

在这里插入图片描述

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值