【C语言进阶】文件操作:文件的打开与文件的读写以及文本文件和二进制文件

目录

1、为什么使用文件

2、什么是文件 

2.1 程序文件

2.2 数据文件 

2.3 文件名

3、文件的打开和关闭 

3.1文件指针 

3.2文件的打开与关闭 

4、文件的顺序读写 

4.1 几个函数的区别

5、文件随机读写 

 5.1 fseek

5.2 ftell 

5.3 rewind 

6、文本文件和二进制文件 

7、文件读取结束的判定 

 7.1 被错误使用的feof

8、文件缓冲区



1、为什么使用文件

我们学习结构体时,写了静态通信录,可以在通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,数据又要重新录入,当程序退出时,通讯录中的数据就不存在了,等下次运行通讯录,数据又要重新录入。我们想既然是通讯录就应该把信息记录下来,只有我们删除数据时,数据才不复存在。

使用文件主要是为了数据持久化、用户交互和数据交换。文件可以存储数据,即使程序关闭或计算机重启,数据也不会丢失。同时,文件也是程序与用户之间以及不同程序之间交换信息的重要媒介。

2、什么是文件 

磁盘上的文件就是文件,但在程序设计中,我们一般只谈程序文件和数据文件

2.1 程序文件

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

2.2 数据文件 

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

这篇文章所要讨论的是数据文件。以前所处理的数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘文件。

2.3 文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。文件名包含3部分:文件路径+文件名主干+文件后缀

比如:c:\code\test.txt

3、文件的打开和关闭 

3.1文件指针 

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

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

//文件类型声明
typedef struct _iobuf
{char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_temfname;
}FILE;

不同的C编译器的FILE类型包含的内容不完全相同,但基本差不多。

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不用过于担心。

一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便

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

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

3.2文件的打开与关闭 

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。

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

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

//打开文件
FILE* fopen(const char* filename, const char* mode);//filename是文件名,mode是文件打开模式(读或写)
//关闭文件
int fclose(FILE* stream);

文件的使用: 

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{FILE* pf=fopen("test.txt", "r");//在对应路径创建文件名为“text”,系统默认扩展名为txtif (pf == NULL){printf("%s\n", strerror(errno));return 1;}//读文件//......//关闭文件fclose(pf);pf = NULL;return 0;
}
文件使用方式含义如果指定文件不存在
"r"(只读)为了输入数据打开一个已经存在的文本文件出错
"w"(只写)为了输出数据打开一个文本文件建立一个新文件
"a"(追加)向文本文件尾添加数据建立一个新文件
"rb"(只读)为了输入数据打开一个二进制文本出错
"wb"(只写)为了输出数据打开一个二进制文本建立一个新文件
"ab"(追加)向一个二进制文件尾添加数据出错
"r+"(读写)为了读和写打开一个文本文件出错
"w+"(读写)为了读和写建立一个文本文件建立一个新文件
"a+"(读写)打开一个文件,在文件尾进行读写建立一个新文件
"rb+"(读写)为了读和写打开一个二进制文件出错
"wb+"(读写)为了读和写新建一个二进制文件建立一个新文件
"ab+"(读写)为了追加和读新建一个二级制文本建立一个新文件

4、文件的顺序读写 

功能函数名适用场景
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件
/举个栗子
#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{FILE* pf = fopen("text.txt.txt", "w");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//写文件char i = 0;for (i = 'a'; i <= 'z'; i++){fputc(i, pf);}//关闭文件fclose(pf);pf == NULL;return 0;
}

其他函数就不在这里一一举例了,大家可以在cplusplus.com官网查看函数的使用方法 

 注意:如果文件里面有原始数据,我们在写文件时会把原始数据给覆盖掉,如果不想销毁就改成追加。

4.1 几个函数的区别

 scanf:是针对标准输入的的格式化输入语句

 printf:是针对标准输出的的格式化输出语句

 fscanf:是针对所有输入流的格式化输入语句

 fprintf: 是针对所有输出流的格式化输出语句

 sscanf:从一个字符串中转换出格式化的数据

 sprintf:是把一个格式化的数据转换成字符串

//sprintf
//int sprintf(char* str, const char* format, ...);
//将格式化数据写入字符串
struct S
{char name[20];int age;float score;
};
int main()
{struct S s = { "张三",20,50.5f };char buffer[100] = { 0 };sprintf(buffer, "%s %d %f\n", s.name, s.age, s.score);printf("%s\n", buffer);//字符串打印(此时已经转化为字符串)//sscanf//int sscanf(const char* s, const char* format, ...);//从字符串中读取格式化数据sscanf(buffer, "%s %d %f", s.name, &(s.age), &(s.score));printf("%s %d %lf\n", s.name, s.age, s.score);return 0;
}

5、文件随机读写 

 5.1 fseek

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

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

//文件中放的是abcdef
int main()
{FILE* pf = fopen("text.txt.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//定位文件指针fseek(pf, 2, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);//关闭文件fclose(pf);pf == NULL;return 0;
}

5.2 ftell 

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

long int ftell (FILE* sream);

int main()
{FILE* pf = fopen("text.txt.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//定位文件指针fseek(pf, 2, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);printf("%d\n", ftell(pf));//关闭文件fclose(pf);pf == NULL;return 0;
}

5.3 rewind 

 让文件指针的位置回到文件的起始位置

void rewind(FILE* stream);

int main()
{FILE* pf = fopen("text.txt.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//定位文件指针fseek(pf, 2, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);printf("%d\n", ftell(pf));rewind(pf);ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf == NULL;return 0;
}

6、文本文件和二进制文件 

根据数据的组织形式,数据文件被称为文本文件二进制文件。根据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件;如果要求在外存上以ASCII码值的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

一个数据在内存中是如何存储的?

字符一律以ASCII码值的形式存储,数值型数据既可以用ASCII形式存储,也可以用二进制形式存储;如果有整数10000,以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节

int main()
{int a = 100000;FILE* pf=fopen("text.txt.txt", "wb");if (pf == NULL){perror("fopen");return 1;}fwrite(&a, 4, 1, pf);fclose(pf);pf = NULL;return 0;
}

7、文件读取结束的判定 

 7.1 被错误使用的feof

 注意:在文件读取过程中,不能用feof函数的返回值直接用来判断文件是否结束。而是应用于当文件文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

1、文本文件读取是否结束,判断返回值是否为EOF(fgetc)或NULL(fgets)

2、二进制文件读取结束判断,判断返回值是否小于实际要读的个数 

8、文件缓冲区 

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

#include<stdio.h>
#include<Windows.h>
int main()
{FILE* pf = fopen("test.txt.txt", "w");fputs("abcdef", pf);printf("睡眠10秒-已经写数据,打开test.txt.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将缓冲区的数据写到文件printf("再睡眠10秒-此时再次打开test.txt.txt文件,文件有内容了\n");Sleep(10000);fclose(pf);//关闭文件时也会刷新缓冲区pf = NULL;return 0;
}

 结论:因为缓冲区的存在,C语言在操作文件时,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。否则可能导致读写文件的问题!

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

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

相关文章

springboot+vue+mybatis超市管理-简单版+PPT+论文+讲解+售后

使用旧方法对超市信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在超市信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的小型超市管理系统有管理员&…

MyCat面试题及参考答案(3万字长文)

目录 什么是MyCat? MyCat的主要功能是什么? MyCat和MySQL Proxy有什么区别?

Java基础(5) 面向对象编程2

目录 一、关键词&#xff1a;this 1.定义 2.作用 &#xff08;1&#xff09;实例方法或构造器中使用当前对象的成员 &#xff08;2&#xff09;同一个类中构造器互相调用 二、方法的重写 1.定义 2.要求 3.代码 4.区分重载和重写 三、关键字&#xff1a;super 1.定义…

探索DIYGW可视化开发工具:提升UniApp项目效率与质量的新途径

一、引言 在快速迭代和不断创新的移动应用开发领域中&#xff0c;开发者们常常面临着一个共同的挑战&#xff1a;如何在保证开发质量的同时&#xff0c;缩短开发周期。近期&#xff0c;一款名为DIYGW的可视化开发工具进入了我们的视野&#xff0c;它以其独特的拖拽式开发方式和…

AI前沿技术探索:智能化浪潮下的创新与应用

一、引言 随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;已成为推动社会发展的重要力量。从自动驾驶汽车到智能医疗诊断&#xff0c;从智能家居到虚拟助手&#xff0c;AI技术正逐渐渗透到我们生活的方方面面。本文旨在探讨AI的前沿技术、创新应用以及未来…

算法题-给定一个日期,输出星期几

目录 给定日期&#xff0c;输出对应是星期几 测试结果 如1900年 5月6日是星期三&#xff0c;计算给的日期是星期几 给定日期&#xff0c;输出对应是星期几 #include <stdio.h> #include <stdlib.h> #include <string.h>int main() {char input[100];int d…

TypeScript算法每日一题:两数之和(1)

作者&#xff1a;前端小王hs 阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主 题库&#xff1a;力扣 题目序号&#xff1a;1&#xff08;简单&#xff09; 题目&#xff1a; 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该…

如何被谷歌收录?

最简单的方法就是提交网站给谷歌&#xff0c;但这种方法可操作空间不大&#xff0c;一天一般也就只有十条左右的链接可以提交&#xff0c;对于一些大网站来说&#xff0c;这种方法显然不适用&#xff0c;这时候GPC爬虫池的好处就体现了&#xff0c;GPC爬虫池对希望提升Google搜…

力扣每日一题 6/1

2928.给小朋友们分糖果[简单] 题目&#xff1a; 给你两个正整数 n 和 limit 。 请你将 n 颗糖果分给 3 位小朋友&#xff0c;确保没有任何小朋友得到超过 limit 颗糖果&#xff0c;请你返回满足此条件下的 总方案数 。 示例 1&#xff1a; 输入&#xff1a;n 5, limit 2 …

Deepin Linux 深度 V23 beige 官方源及换镜像源方法。

Deepin Linux 深度 V23 英文版本号&#xff1a;beige 谁起的烂名字。。。。。。 1. 打开文件管理器&#xff0c;在apt文件夹点右键&#xff08;以管理员身份打开&#xff09;&#xff0c; 2. 输入你的登录密码&#xff0c;以便打开文件夹&#xff08;管理员权限&#xff09;。…

【MySQL数据库】索引与事务

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【MySQL】探秘&#xff1a;数据库世界的瑞士军刀 目录 &#x1f5f3;️一.索引 &#x1f4ee;1.工作原理 &#x1f4ec;2.类型 &#x1f4ed;3.作用 &#x1f4ea;4.优缺点 &#x1f4eb;5.使用…

【Modelground】个人AI产品MVP迭代平台(2)——网站从0-1部署教程

文章目录 1.选购一台云服务器2. 购买域名3. 通过nginx部署静态网站4. 通过gitee在云服务器拉取代码5. ICP备案总结 1.选购一台云服务器 目前阿里云在促销&#xff0c;一台2核2GB内存3Mbps宽带的云服务器&#xff0c;一年只需要99元&#xff0c;学生更便宜&#xff0c;我认为这…

Java——处理键盘输入

在Java中&#xff0c;可以使用多种方式来处理键盘输入。最常用的一种方法是使用 Scanner 类&#xff0c;它位于 java.util 包中。 一、使用 Scanner 类处理键盘输入 1、具体操作步骤 1&#xff09;导入 Scanner 类 在开始编写代码之前&#xff0c;需要导入 java.util.Scann…

C++ 类与构造函数 三五法则

前言 本文介绍C中类的基础知识&#xff0c;介绍所有的构造函数&#xff0c;和什么时候应该该写哪些构造函数&#xff0c;并介绍经典的三五法则。 在C中&#xff0c;只是声明一个空类&#xff0c;不做任何事情的话&#xff0c;编译器会自动为你生成如下八个默认函数&#xff1…

mysql表GEOMETRY记录的读取与增加

两张表&#xff0c;均有GEOMETRY字段&#xff0c;合并成一张表。 直接读取记录并insert into 出错&#xff0c;需用AsText(SHAPE) 及 GeomFromText($v[1])转换 一、读取 $tStr "select OGR_FID,AsText(SHAPE),name,area,perimeter,cnty_,cnty_id,cnty_code,pyname,post…

CentOS8安装opensips-cli

环境&#xff1a;阿里云 操作系统CentOS8.5 opensips 3.x版本废弃了之前的配置管理脚本opensipsctl&#xff0c;引入了一个新的python工具叫opensips-cli。本文描述如何在CentOS8安装这个工具。 升级python CentOS 8默认的ptyhon版本是3.6。这不能满足opensips-cli的要求&…

信息化业务运维的必要性和重要性

随着信息技术的飞速发展&#xff0c;企业信息化已经成为提升竞争力的关键手段。然而&#xff0c;仅仅拥有先进的信息化系统并不足以保证企业的高效运转&#xff0c;对这些系统进行科学、有效的运维同样至关重要。本文将深入探讨信息化业务运维的必要性和重要性。 一、信息化业…

什么是股票,新手如何入门

股票是代表公司所有权的证券&#xff0c;当你持有某公司的股票时&#xff0c;你实际上拥有了该公司的一部分。作为股东&#xff0c;你有权分享公司的利润&#xff08;如通过股息&#xff09;&#xff0c;以及在公司解散时对公司剩余资产的索取权。以下是关于股票的一些基本概念…

【TB作品】MSP430F5529,单片机,电子秒表,秒表

硬件 MSP430F5529开发板7针0.96寸OLED /* OLED引脚分配 绿色板子DO(SCLK)------P4.3D1(DATA)------P4.0RES-----------P3.7DC------------P8.2CS------------P8.1 */ 程序功能 该程序是一个用C语言编写的&#xff0c;用于msp430f5529微控制器上的简单电子秒表应用。它使用…

iOS与前端:深入解析两者之间的区别与联系

iOS与前端&#xff1a;深入解析两者之间的区别与联系 在数字科技高速发展的今天&#xff0c;iOS与前端技术作为两大热门领域&#xff0c;各自在移动应用与网页开发中扮演着不可或缺的角色。然而&#xff0c;这两者之间究竟存在哪些差异与联系呢&#xff1f;本文将从四个方面、…