C语言中常用的文件操作

news/2024/4/27 13:41:48/文章来源:https://blog.csdn.net/weixin_56898048/article/details/137042973

本文将介绍常用的关于文件操作函数,如fopen,fclose,fread,fwrite,feek,ftell,rewind以及feof和ferror等文件操作操作函数,还介绍一些用于所有输入输出流的函数如fgetc,fputc,fgets,fputs,fprintf,fscanf等函数,还介绍了sscanf,sprintf函数,feof和ferror函数。最后介绍了文件文件缓冲区的存在。

目录

1、文件的介绍

2、文件的打开和关闭

①流的介绍

②文件指针

③文件的打开和关闭

④顺序读写函数介绍 

(1)fgetc函数介绍

(2) fputc函数介绍

(3)fgets函数介绍

(4)fputs函数介绍

(5)fscanf函数介绍

(6)fprintf函数介绍

(7)fwrite函数介绍

(8)fread函数介绍

3、scanf,printf,sscanf,sprintf,fscanf,fscanf函数的区别

(1)sscanf函数介绍

(2)sprintf函数介绍

4、文件的随机读写

(1)ftell函数介绍

(2)rewind

5、文件读取结束的判定 

feof函数介绍

ferror函数介绍

6、文件缓冲区


1、文件的介绍

我们写的程序的数据是存储在电脑的内存中,当程序退出,内存回收,数据就会丢失,当再次想要看到上次程序的结果是看不到的,想要将数据进行持久化的保存(程序退出其数据不丢失),我们可以使用文件来对这些数据进行保存。

从文件功能方面来分类,文件有程序文件和数据文件。程序文件包括源程序文件(如后缀为.c文件),目标文件(Windows系统其后缀名为.obj),可执行文件(Windows系统下其后缀名为.exe)。数据文件,其文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件或输出内容的文件。下面介绍的是数据文件。根据数据的组织形式,数据文件被称为二进制文件和文本文件,如果数据在内存中以二进制的形式存储(不经任何转换),直接输出到外存文件中,这就是二进制文件。如果在外存中以ASCII码的形式存储,在存储前需要进行转换,以ASCII码的形式存储的文件就是文本文件。数据存储到外存的这个文件即可以二进制的形式进行存储也可以ASCII码的形式进行存储。这个区分主要是看这个外存(硬盘)里的存储的是二进制还是ASCII码的形式。注意,计算机中的数据在内存中都是二进制进行存储的,是文本文件还是二进制文件是针对外存(也就是硬盘来说的)。

2、文件的打开和关闭

①流的介绍

程序的数据可能会输出到各种外部设备,也可能从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,所以就抽象出来了流的概念。C语言程序对文件,画图,键盘等数据的输入操作都是通过流操作的。一般情况下,要想向流里写数据或者从流中读取数据都是要打开流然后进行操作。

值得注意的是,从键盘输入数据和向屏幕里打印信息都没有打开流,这是由于C语言程序在启动的时候默认打开了3个流(stdin,stdout,stderr)。

stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输入流中读取数据。
stdout - 标准输出流,大多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
stderr - 标准错误流,大多数环境中输出到显示器界面。
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;

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。每当打开⼀个文件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信息,使⽤者不必关心其细节。⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
下面创建一个FILE*的指针变量

FILE* pf;//⽂件指针变量

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

③文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件,打开文件的同时都会返回一个FILE*的指针变量指向该文件,这就相当于简历了指针和文件的关系。ANSIC规定使用fopen函数来打开文件,fclose来关闭文件。

//打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件
int fclose ( FILE * stream );

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");//以写的形式打开data.txt文件if (pf == NULL){perror("fopen");return 1;}//进行文件操作//关闭文件fclose(pf);pf = NULL;return 0;
}

④顺序读写函数介绍 

所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀般指适⽤于标准输出流和其他输出流(如⽂件输出流)。

需要注意的是,对流进行操作的时候一定要与对应的函数就行操作,如对文件操作,对文件以读的形式打开那就只能读取文件的信息而不能向文件输出信息,同样地,如果以写的形式打开,那就只能对文件进行写操作而不能对其进行读操作,如果需要又读又写那就需要再打开文件的时候设定读写的模式。

(1)fgetc函数介绍

FILE*表示一个流,(如文件流或标准输入输出流),该函数读取流中的一个字符,当读到文件末尾或读取错误的时候会返回一个EOF。当需要将一个流的信息都读取出来可以使用这个函数一个字符一个字符的读取直至返回值为EOF(读取结束),下面将使用代码展示

代码示例:

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");//以读的形式打开data.txt文件if (pf == NULL){perror("fopen");return 1;}//进行文件操作char ch = 0;while ((ch = fgetc(pf)) != EOF)//当fgetc返回值不为EOF就表示在没有读取失败或还没到文件末尾{printf("%c", ch);}//关闭文件fclose(pf);pf = NULL;return 0;
}

其中data.txt文件(与C语言的源文件在同一个目录底下)的内容如下:

最后结果如下: 

(2) fputc函数介绍

该函数的功能是向流中写一个字符 ,如果写入成功将返回该字符,写入失败就会返回EOF。

代码示例:

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");//以读的形式打开data.txt文件if (pf == NULL){perror("fopen");return 1;}//进行文件操作,向data.txt文件写入一个字符xfputc('x', pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

(3)fgets函数介绍

该函数是向流中的数据读取num个字符将其放到str这个指针所指向的空间。如果读取成功就返回str(其实就是这个字符串的地址),如果读取失败或读到文件结尾就会返回NULL。当需要将一个流的信息都读取出来可以使用这个函数一次读取num个,直至返回值为NULL(读取结束),下面将使用代码展示

代码示例:

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");//以读的形式打开data.txt文件if (pf == NULL){perror("fopen");return 1;}char ch[20] = { 0 };while (fgets(ch, 5, pf)!=NULL)//将data.txt文件的内容每次读取5个放到ch数组中,直至读取错误或文件末尾{printf("%s", ch);//将读取的}//关闭文件fclose(pf);pf = NULL;return 0;
}

(4)fputs函数介绍

该函数是将str指向的内容写到流中,如果写入成功就会返回应该非0的数,如果写入失败就会返回0。

代码示例:

#include<stdio.h>
int main()
{FILE* pf = fopen("data.txt", "w");//以读的形式打开data.txt文件if (pf == NULL){perror("fopen");return 1;}char ch[30] = "asdfahyrhdfgqefd7890";fputs(ch, pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

(5)fscanf函数介绍

该函数的功能是从流中读取数据并按特定的格式存储到format这个参数里(这个参数与scanf类似)。如果在读取过程中发生读取错误或到达文件末尾,会设置相应的指示器(feof或ferror)。如果在任何数据成功读取之前发生其中之一,则返回EOF。

代码示例:

#include<stdio.h>
int main()
{char ch[30] = { 0 };FILE* pf = fopen("data.txt", "r");//以读的形式打开文件fscanf(pf, "%s", ch);printf("%s\n", ch);return 0;
}

 (6)fprintf函数介绍

该函数是将format所指向的字符内容输出到stream这个流中,如果发生写入错误,文件错误指示器(ferror)会被设置,同时函数通常会返回一个负数,用以表示错误的发生。如果成功的话就会返回写入流中字符的个数。

代码示例:

#include<stdio.h>
int main()
{char ch[30] = "12345679zxcvasdfbgre";FILE* pf = fopen("data.txt", "w");//以写的形式打开文件fprintf(pf, "%s", ch);printf("%s\n", ch);return 0;
}

 

 (7)fwrite函数介绍

该函数是将ptr所指向的size*count个字节的内容写入到流中,返回值成功写入的个数。该函数是对二进制文件进行操作的。

#include<stdio.h>
int main()
{char ch[30] = "12345679zxcvasdfbgre";FILE* pf = fopen("test", "wb");//以二进制读写的形式打开文件fwrite(ch,sizeof(char), sizeof(ch), pf);//char tmp[30] = { 0 };//fread(tmp, sizeof(char), sizeof(tmp), pf);//printf("%s\n", tmp);return 0;
}

(8)fread函数介绍

该函数向流中取size*count个字节的数据放入到ptr所指向的空间。返回的是读取成功的个数。可以通过每次读取一个直至返回值为0就表示读取结束或读取失败。这可以通过ferror或feof来对其进行判断,看是正常结束还是不正常结束。需要注意的是该函数是对二进制文件进行读取的

代码示例:

#include<stdio.h>
int main()
{//char ch[30] = "12345679zxcvasdfbgre";FILE* pf = fopen("test", "rb");//以二进制读写的形式打开文件//fwrite(ch,sizeof(char), sizeof(ch), pf);char tmp[30] = { 0 };fread(tmp, sizeof(char), sizeof(tmp), pf);printf("%s\n", tmp);return 0;
}

需要注意的是,这些函数如果对文件流进行操作时,打开文件的时候要留意是读文件还是写文件,可以从文件中读取的有fgetc,fgets,fscanf,fread函数。而将数据输出到文件中的函数有fputc,fputs,fprintf,fwrite函数。fwrite和fread只能针对文件流进行操作(还是以二进制进行操作的),而上面其余的函数是针对所以输入或输出流。

3、scanf,printf,sscanf,sprintf,fscanf,fscanf函数的区别

 (1)sscanf函数介绍

 该函数是在字符串读取格式化的数据。

代码示例:

#include<stdio.h>
int main()
{char str[15] = "10 1.23 avb";int a = 0;float b = 0;char ch[5] = { 0 };sscanf(str, "%d%f%s", &a, &b, ch);printf("%d\n", a);printf("%f\n", b);printf("%s\n", ch);return 0;
}

(2)sprintf函数介绍

 

该函数是把格式化的数据转化成字符串

#include<stdio.h>
int main()
{char str[30] = "10 1.23 avb";int a = 0;float b = 0;char ch[5] = { 0 };char tmp[30] = { 0 };sscanf(str, "%d%f%s", &a, &b, ch);sprintf(tmp, "%d %f %s", a, b, ch);printf("%s", tmp);return 0;
}

小结:scanf从标准输入流读取格式化数据,fscanf从指定的输入流上读取格式化的数据,sscanf在字符串中读取格式化的数据。printf把数据以格式化的形式打印在标准输出流上,fprintf把数据以格式化的形式输出到指定的流,sprintf把格式化的数据转化成字符串。

4、文件的随机读写

(1)fseek函数介绍

#include<stdio.h>
int main()
{FILE*pf=fopen("tt.txt", "w");if (pf == NULL){perror("fopen");return 1;}fputs("This is an apple.", pf);fseek(pf, 9, SEEK_SET);//通过设置后两个参数,来设定光标的位置fputs(" sam", pf);char ch = 0;while ((ch=fgetc(pf))!=EOF){printf("%c", ch);}fclose(pf);return 0;
}

 (1)ftell函数介绍

 

该函数是返回文件指针相对于于起始位置的偏移量

#include<stdio.h>int main()
{FILE*pf=fopen("tt.txt", "w");if (pf == NULL){perror("fopen");return 1;}fputs("This is an apple.", pf);fseek(pf, 9, SEEK_SET);fputs("xxx",pf);int ret=ftell(pf);printf("%ld\n", ret);//打印的是光标相对于起始的偏移量return 0;
}

(3)rewind

让光标回到文件的起始位置。

#include<stdio.h>int main()
{FILE*pf=fopen("tt.txt", "w");if (pf == NULL){perror("fopen");return 1;}fputs("This is an apple.", pf);fseek(pf, 9, SEEK_SET);fputs("xxx",pf);int ret=ftell(pf);printf("%ld\n", ret);//打印的是光标相对于起始的偏移量rewind(pf);ret = ftell(pf);printf("%ld\n", ret);//打印的是光标相对于起始的偏移量return 0;
}

5、文件读取结束的判定 

feof函数介绍

在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。如果是遇到文件末尾结束的话就会返回一个非0的数,如果不是文件末尾结束的话将返回0。

ferror函数介绍

如果设置了与流关联的错误指示符,则返回一个非零值。否则,返回0。

6、文件缓冲区

ANSIC标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为
程序中每⼀个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓
冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小是根据C编译系统决定的。

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。如果不刷新缓冲区或关闭文件可能会导致数据丢失等问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1026599.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主流电商平台淘宝/1688/京东电商数据实时采集监测|电商API接口接入

电商大数据平台基于网络主流电商平台淘宝/1688/京东电商数据进行搭建&#xff0c;全面监测了包含淘宝、京东、苏宁、美团、大众点评等共计100余个主流电商交易平台&#xff0c;并凭借多年的电子商务数据分析挖掘经验积累形成的电商数据清洗体系和挖掘模型&#xff0c;能高效完成…

DashVector - 阿里云向量检索服务

DashVector 文章目录 DashVector一、关于 DashVector二、使用 DashVector 前提准备1、创建Cluster&#xff1a;2、获得API-KEY3、安装最新版SDK 三、快速使用 DashVector1. 创建Client2. 创建Collection3、插入Doc4、相似性检索5、删除Doc6. 查看Collection统计信息7. 删除Coll…

Flask 与小程序 的图片数据交互 过程及探讨研究学习

今天不知道怎么的&#xff0c;之前拿编程浪子地作品抄过来粘上用好好的&#xff0c;昨天开始照片突的就不显示了。 今天不妨再耐味地细细探究一下微信小程序wxml 和flask服务器端是怎么jpg图片数据交互的。 mina/pages/food/index.wxml <!--index.wxml--> <!--1px …

Python程序设计 循环结构(二)

1.斐波那契数列 编写一个能计算斐波那契数列中第x个数的小程序。斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列、 因数学家莱昂纳多斐波那契&#xff08;Leonardoda Fibonacci&#xff09;以兔子繁殖为例子而引入&#xff0c;故又称为…

日本EPSON 爱普生HUD汽车抬头显示系统芯片

目前HUD产品在新车上的配装率逐年上升&#xff0c;预计在2025年将达到30%。那么在介绍爱普生HUD整合方案之前&#xff0c;让我们先了解一下什么叫HUD。 HUD&#xff08;Head Up Display&#xff09;中文叫抬头显示系统&#xff0c;又被叫做平行显示系统。早被应用在飞机辅助…

Linux系统——硬件命令

目录 一.网卡带宽 1.查看网卡速率——ethtool 网卡名 2.查看mac地址——ethtool -P 网卡名 二、内存相关 1.显示系统中内存使用情况——free -h 2.显示内存模块的详细信息——dmidecode -t memory 三、CPU相关 1.查看CPU架构信息——lscpu 2.性能模式 四、其他硬件命…

C语言例4-37:输出10~100的全部素数

素数是指除1和它本身之外不能被其他任何整数整除。 自己思考的基础代码如下&#xff1a; //输出10~100的全部素数 //素数是指除1和它本身之外不能被其他任何整数整除 //自己思考的基础代码 #include<stdio.h> int main(void) {int n10,i2,m,counter0; // n10~100;for(n…

如何用Flask中的Blueprints构建大型Web应用

本文分享自华为云社区《构建大型Web应用Flask中的Blueprints指南》&#xff0c;作者&#xff1a; 柠檬味拥抱。 什么是Blueprints&#xff1f; 什么是Blueprints&#xff1f; Blueprints是Flask中的一种模式&#xff0c;用于将应用程序分解为可重用的模块。每个蓝图实际上是…

IDEA | 资源文件中文乱码问题解决

问题 IDEA打开资源文件&#xff0c;显示乱码问题。 解决方案 1、电脑是mac&#xff0c;点击IDEA->【Preferences】->【Editor】->【File Encodings】 2、选择【Properties Files】中的UTF-8&#xff0c;并勾选Transparent native-to-ascii conversion。 3、最后点击…

蓝桥杯算法赛(二进制王国)

问题描述 二进制王国是一个非常特殊的国家&#xff0c;因为该国家的居民仅由 0 和 1 组成。 在这个国家中&#xff0c;每个家庭都可以用一个由 0 和 1 组成的字符串 S 来表示&#xff0c;例如 101、 000、 111 等。 现在&#xff0c;国王选了出 N 户家庭参加邻国的庆典…

Karmada 管理有状态应用 Xline 的早期探索与实践

背景与动机 目前随着云原生技术和云市场的不断成熟&#xff0c;越来越多的 IT 厂商开始投入到跨云多集群的怀抱当中。以下是 flexera 在 2023 年中关于云原生市场对多云多集群管理的接受程度的调查报告&#xff08;http://info.flexera.com&#xff09; 从 flexera 的报告中可…

python_1

要求&#xff1a; 代码&#xff1a; # 先将分钟数转化成年数&#xff0c;再将余数做为天数 minute float(input("请输入分钟数&#xff1a;")) year_1 (minute / 60 / 24) // 365 day_1 (minute / 60 / 24) % 365 now f"{minute}分钟{year_1}年{day_1}天&q…

Polkadot、Kusama 和六大领先平行链现已上线 Dune 数据分析平台!

3 月 19 日对于波卡社区来说是一个关键性的时刻&#xff0c;因为 Polkadot 数据首次在领先的区块链数据开源分析平台 Dune 上可以被访问和使用。这是 Colorful Notion 和 Dune 之间战略合作的结果&#xff0c;这次的合作与集成将使 Polkadot 生态系统的可见性大幅增强&#xff…

力扣面试150 阶乘后的零 数论 找规律 质因数

Problem: 172. 阶乘后的零 思路 &#x1f468;‍&#x1f3eb; 大佬神解 一个数末尾有多少个 0 &#xff0c;取决于这个数 有多少个因子 10而 10 可以分解出质因子 2 和 5而在阶乘种&#xff0c;2 的倍数会比 5 的倍数多&#xff0c;换而言之&#xff0c;每一个 5 都会找到一…

HTML 常用标签总结

本篇文章总结了一些我在学习html时所记录的标签&#xff0c;虽然总结并不是非常全面&#xff0c;但都是一些比较常用的。 html元素标签 首先一个html界面是由无数个元素标签组成的&#xff0c;每个元素具有它的属性 1.input 单行文本框 标签type属性——text <input ty…

机器学习周记(第三十一周:文献阅读-GGNN)2024.3.18~2024.3.24

目录 摘要 ABSTRACT 1 论文信息 1.1 论文标题 1.2 论文模型 1.2.1 数据处理 1.2.2 门控图神经网络 1.2.3 掩码操作 2 相关知识 2.1 图神经网络&#xff08;GNN&#xff09; 2.2 图卷积神经网络&#xff08;GCN&#xff09; 3 相关代码 摘要 本周阅读了一篇利用图神…

IDEA2023版本整合SpringBoot热部署

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 开发环境篇 ✨特色专栏&#xff1a; M…

波奇学Linux:自定义协议和序列和反序列化

TCP是面向字节流的如何保证&#xff0c;读取上来的数据是一个"完整"的报文 tcp传输控制协议&#xff1a;什么时候发&#xff0c;发多少&#xff0c;出错怎么办 read和write都是从用户到内核空间的拷贝&#xff0c;数据不一定传输到另一个台主机的缓冲区&#xff0c;…

精品凉拌菜系列热卤系列课程

这一系列课程涵盖精美凉拌菜和美味热卤菜的制作技巧。学员将学习如何选材、调味和烹饪&#xff0c;打造口感丰富、色香俱佳的菜肴。通过实践训练&#xff0c;掌握独特的烹饪技能&#xff0c;为家庭聚餐或职业厨艺提升增添亮点。 课程大小&#xff1a;6.6G 课程下载&#xff1…

IDEA 远程调试

1.什么是远程调试 Java提供了一个远程调试功能&#xff0c;支持设置断点及线程级的调试同时&#xff0c;不同的JVM通过接口的协议联系&#xff0c;本地的Java文件在远程JVM建立联系和通信。 2.服务端开启远程调试 开启远程调试功能&#xff0c;需要修改tomcat 的catalina.sh…