(C语言)文件操作与函数,超详解

目录

1. 文件

1.1  为什么使用文件?

1.2 什么是文件?

1.2.1 程序文件

1.2.2 数据文件

1.3 文件名

1.4 二进制文件和文本文件

2. 文件的打开和关闭

2.1 流和标准流

2.1.1 流

2.1.2 标准流

2.2 文件指针

2.3 文件的打开和关闭

3. 文件的顺序读写

3.1 顺序读写函数介绍

3.1.1 fgetc 与 fputc

3.1.2 fgets 与 fputs

3.1.3 fprintf与 fscanf

3.1.4 fread 与 fwrite

3.1.5 sscanf 与 sprintf

4. 文件的随机读写

4.1 fseek函数

4.2 ftell函数

4.3 rewind函数

5  文件读取结束的判定

5.1 feof函数与ferror函数

6. ⽂件缓冲区


1. 文件

1.1  为什么使用文件?

如果没有文件 ,我们写的程序的数据是存储在电脑的内存中 ,如果程序退出 ,内存回收 ,数据就丢失 ,等再次运行程序 ,是看不到上次程序的数据的 ,如果要将数据进行持久化的保存 ,我们可以使用文件。

1.2 什么是文件?

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

1.2.1 程序文件

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

1.2.2 数据文件

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

本章讨论的是数据文件。在以前处理数据的输入输出都是以终端为对象的 ,即从终端的键盘输入数据 ,运行结果显示到 显示器上。

其实有时候我们会把信息输出到磁盘上  当需要的时候再从磁盘上把数据读取到内存中使用 ,这里处理的就是磁盘上文件。

1.3 文件名

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

文件名命名有一些禁止使用的字符如:/ \ : * ? < > 空格 还有一些特殊字符。

文件名不是必须要加后缀名的。

为了方便起见 ,文件标识常被称为文件名。

1.4 二进制文件和文本文件

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

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

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

一个数据在内存中是怎么存储的呢?

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

如有整数10000 ,如果以ASCII码的形式输出到磁盘 则磁盘中占用5个字节(每个字符一个字节),  二进制形式输出 ,则在磁盘上只占4个字节(VS2019测试)。

2. 文件的打开和关闭

2.1 流和标准流

2.1.1 流

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

C程序针对文件、 画面、键盘等的数据输入输出操作都是通过流操作的。

一般情况下 ,我们要想向流里写数据 ,或者从流中读取数据 ,都是要打开流 ,然后操作。

2.1.2 标准流

那为什么我们从键盘输入数据,向屏幕上输出数据 ,并没有打开流呢?

那是因为C语言程序在启动的时候 默认打开了3个流

.  stdin - 标准输入流 ,在大多数的环境中从键盘输入 scanf函数就是从标准输入流中读取数据。

.  stdout - 标准输出流 ,大多数的环境中输出至显示器界面 ,printf函数就是将信息输出到标准输出流中。

.  stderr - 标准错误流 ,大多数环境中输出到显示器界面。

这是默认打开了这三个流 ,我们使用scanf、printf等函数就可以直接进行输入输出操作的。

stdin、stdout、stderr 三个流的类型是: FILE* ,通常称为文件指针。

C语言中 ,就是通过  FILE*  的文件指针来维护流的各种操作的。

2.2 文件指针

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

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

例如 ,VS2013编译环境提供的  stdio.h 头文件中有以下的文件类型申明:

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

每当打开一个文件的时候 ,系统会根据文件的情况自动创建一个FILE结构的变量 ,并填充其中的信 ,使用者不必关心细节。一般都是通过一个FILE*的指针来维护这个FILE结构的变量 ,这样使用起来更加方便。

下面我们可以创建一个FILE*的指针变量:

FILE* pf;

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

2.3 文件的打开和关闭

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

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

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

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

const char  *filename是要要打开的文件名字。

mode表⽰⽂件的打开模式,下⾯都是⽂件的打开模式:
(filename和mode都要用英文的 "  "引起来)

演示:

int main()
{//打开文件FILE* pf = fopen("date.txt", "w");//检查是否成功打开文件if (pf == NULL){perror("fopen");return 1;}//操作文件fputs("this is a example", pf);//关闭文件fclose(pf);return 0;
}

3. 文件的顺序读写

3.1 顺序读写函数介绍

上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀ 般指适⽤于标准输出流和其他输出流(如⽂件输出流)
下面我们来详细学习一下这些函数:

3.1.1 fgetc 与 fputc

详见:(C语言) fgetc与fputc函数详解(本人的另一篇文章)http://t.csdnimg.cn/UYMPPicon-default.png?t=N7T8http://t.csdnimg.cn/UYMPP

3.1.2 fgets 与 fputs

详见(C语言)fgets与fputs函数详解(本人的另一篇文章)
http://t.csdnimg.cn/TU86Wicon-default.png?t=N7T8http://t.csdnimg.cn/TU86W

3.1.3 fprintf与 fscanf

详见 (C语言)fscanf与fprintf函数详解(本人的另一篇文章)
http://t.csdnimg.cn/O4Fezicon-default.png?t=N7T8http://t.csdnimg.cn/O4Fez

3.1.4 fread 与 fwrite

详见(C语言)fread与fwrite详解(本人的另一篇文章)

http://t.csdnimg.cn/qIBJBicon-default.png?t=N7T8http://t.csdnimg.cn/qIBJB

 3.1.5 sscanf 与 sprintf

详解(C语言)sscanf 与 sprintf详解(本人的另一篇文章)

http://t.csdnimg.cn/7j9gJicon-default.png?t=N7T8http://t.csdnimg.cn/7j9gJ

4. 文件的随机读写

4.1 fseek函数

根据文件指针的位置和偏移量来定位文件指针,可以自行控制光标的位置。

参数origin可以填以下的内容:

SEEK_SET表示文件的开头;

SEEK_CUR表示文件光标的当前位置;

SEEK_END表示文件的末尾;

offset是指从origin位置偏移的字符数,可正可负,正表示向后,负表示向前。

演示:

我们现在有date.txt文件,内容如图所示,我们想办法将其中的f字母读取出来。

#include <stdio.h>int main()
{FILE* pf = fopen("date.txt", "r");//将光标定位在f的位置fseek(pf, 5, SEEK_SET);int ch = fgetc(pf);printf("%c", ch);return 0;
}

这样我们从文件向后定位到了f字母,也可以从文件后面向前定位。

#include <stdio.h>int main()
{FILE* pf = fopen("date.txt", "r");//将光标定位在f的位置,从后向前定位fseek(pf, -9, SEEK_END);int ch = fgetc(pf);printf("%c", ch);return 0;
}

当然我们也可以根据需要从当前位置来偏移光标。

4.2 ftell函数

返回文件指针相对于起始位置的偏移量,返回值是long类型

演示:

#include <stdio.h>int main()
{FILE* pf = fopen("date.txt", "r");if (pf == NULL){perror("fopen");return 1;}long sz;fseek(pf, 0, SEEK_END);sz = ftell(pf);printf("size of date.txt is %ld", sz);return 0;
}

这样就返回了文件内容的内容的多少。

4.3 rewind函数

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

这个比较简单,不再过多介绍,和fseek函数

效果是一样的。

5  文件读取结束的判定

5.1 feof函数与ferror函数

feof

ferror

feof函数:当文件读取结束的时候 ,判断是读取结束的原因是否是:遇到文件尾结束。

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

fgetc判断是否为EOF;

fgets判断返回值是否是NULL.;

ferror函数:当文件读取结束时,判断是不是因为发生错误而结束。

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

文本文件操作示例:

#include <stdio.h>
int main()
{FILE* pf = fopen("date.txt", "r");if (pf == NULL){perror("fopen");return 1;}char c;while ((c = getc(pf)) != EOF){printf("%c", c);}//下面判断文件读取是正常结束,还是发生错误结束if (feof(pf)){printf("读取到文件结尾,安全结束");}else if (ferror(pf)){printf("遇到错误");}fclose(pf);return 0;
}

二进制文件操作示例

enum
{size=5
};
#include <stdio.h>
int main()
{//将数据以二进制类型写入文件double arr1[size] = { 1,2,3,4,5 };FILE* fp = fopen("date.txt", "wb");if (fp == NULL){perror("fopen");return 1;}fwrite(arr1, sizeof(arr1[0]), size,fp);//写入完成关闭文件fclose(fp);fp = NULL;//读文件double arr2[size];fp = fopen("date.txt", "rb");size_t count = fread(arr2, sizeof * arr1, size, fp);if (count == size){puts("Array read successfully, contents: ");for (int i = 0; i < size; i++){printf("%lf ", arr2[i]);}printf("\n");}else{if (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) perror("Error reading test.bin");}fclose(fp);return 0;
}

运行结果:

因为是二进制写入的所以我么无法看到文件的内容但是我们通过打印发现文件内容就是我们写入的double类型的1,2,3,4,5

6. ⽂件缓冲区

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

缓冲区的优点:

缓冲区可以减少对物理设备的直接访问次数。当数据被写入或从文件中读取时,操作系统会先将数据放入内存中的缓冲区,而不是直接写入磁盘。这样可以减少磁盘I/O操作的频率,因为多个小的I/O请求可以先在缓冲区中累积,然后一次性写入磁盘。

如果没有缓冲区,每次读写操作都可能需要等待物理设备(如硬盘或网络设备)的响应,这会导致程序运行缓慢。使用缓冲区后,程序可以先与缓冲区交互,而不必每次都等待物理设备的响应。

因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂件。如果不做,可能导致读写⽂件的问题,如果程序运行时发生错误,数据可能就可能没有写入硬盘导致数据丢失。
该内容做了解即可。
感谢观看,欢迎在评论区讨论

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

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

相关文章

Go Web 开发【Gin 框架快速开发】

1、Gin Web 快速开发 1.1、环境准备 1.1.1、导入 gin 依赖 这里就叫 gin 依赖了&#xff0c;在 Goland 命令行中输入下面的命令&#xff1a; go get -u github.com/gin-gonic/gin 1.1.2、设置代理 如果下载失败&#xff0c;最好设置一下代理&#xff0c;在 cmd 命令行中输…

深度学习论文:Local Feature Matching Using Deep Learning: A Survey

深度学习论文: Local Feature Matching Using Deep Learning: A Survey Local Feature Matching Using Deep Learning: A Survey PDF: https://arxiv.org/pdf/2401.17592 1 概述 近年来&#xff0c;深度学习模型的引入引发了对局部特征匹配技术的广泛探索。本文旨在全面概述局…

爬虫学习:基本网络请求库的使用

目录 一、urllib网络库 1.urlopen()方法 2.request方法 二、requests网络请求库 1.主要方法 2.requests.get()和requests.post() 一、urllib网络库 1.urlopen()方法 语法格式&#xff1a; urlopen(url,data,timeout,cafile,capath,context) # url:地址 # data:要提交的数据…

POWERBI==官网教程

地址 COVID-19 tracking sample for US state and local governments - Power BI | Microsoft Learn 已经非常全面了

JSON教程(非常详细)

参考文章来源&#xff1a;JSON教程&#xff08;非常详细&#xff09; 目录 JSON JSON 发展史 为什么要使用 JSON&#xff1f; JSON 的不足 存储格式 使用场景 1) 定义接口 2) 序列化 3) 生成 Token 4) 配置文件 JSON语法规则 JSON 与 JavaScript 对象的区别 JSON数…

解决Pycharm全局搜索与输入法简繁切换快捷键冲突问题

Pycharm中全局搜索快捷键Ctrl Shift F 如图所示&#xff1a; 微软输入法简繁切换快捷键设置&#xff1a; 解决办法&#xff1a; 关掉输入法的切换功能即可&#xff0c;或者更改简繁切换快捷键&#xff0c;毕竟简繁切换使用频率极低。

骑缝电子章怎么盖?

盖骑缝电子章通常涉及几个基本步骤&#xff0c;这里提供一个通用的流程&#xff0c;适用于大多数电子文档处理软件&#xff0c;尤其是那些支持电子签名和印章功能的软件&#xff0c;比如Adobe Acrobat Pro DC、e-章宝(易友EU3000智能盖章软件)等。请注意&#xff0c;具体操作可…

2024年五一数学建模C题完整解题思路代码

2024年第二十一届五一数学建模竞赛题目 C题 煤矿深部开采冲击地压危险预测 煤炭是中国的主要能源和重要的工业原料。然而&#xff0c;随着开采深度的增加&#xff0c;地应力增大&#xff0c;井下煤岩动力灾害风险越来越大&#xff0c;严重影响着煤矿的安全高效开采。在各类深…

路由器的构成

一、路由器简介 路由器是互联网中的关键设备&#xff1a; 连接不同的网络路由器是多个输入端口和多个输出端口的专用计算机&#xff0c;其任务是转发分组&#xff08;转发给下一跳路由器&#xff09;下一跳路由器也按照这种方法处理分组&#xff0c;直到该分组到达终点为止 …

Pandas入门篇(二)-------Dataframe篇4(进阶)(Dataframe的进阶用法)(机器学习前置技术栈)

目录 概述一、复合索引&#xff08;一&#xff09;创建具有复合索引的 DataFrame1. 使用 set_index 方法&#xff1a;2.在创建 DataFrame 时直接指定索引&#xff1a; &#xff08;二&#xff09;使用复合索引进行数据选择和切片&#xff08;三&#xff09;重置索引&#xff08…

使用 Langchain、Langfuse、Nemo-gaurdrails、RAGAs构建 RAG 管道并进行监控和评估

原文地址:build-end-to-end-rag-pipeline-with-monitoring-and-evaluation-using-langchain-azure-ai-search 2024 年 4 月 21 日 介绍 使用现代的LLM框架,如Langchain或llamaindex,可以迅速搭建一个用于 RAG 的管道,通常只需编写大约5-6行代码。然而,若要构建一个适用于生…

【小浩算法 BST与其验证】

BST与其验证 前言我的思路思路一 中序遍历判断数组无重复递增思路二 递归边界最大值最小值的传递 我的代码测试用例1测试用例2 前言 BST是二叉树一个经典应用&#xff0c;我们常常将其用于数据的查找以及构建平衡二叉树等。今天我所做的题目是验证一颗二叉树是否为二叉搜索树&…

MATLAB实现果蝇算法优化BP神经网络预测分类(FOA-BP)

果蝇算法&#xff08;Fruit Fly Optimization Algorithm, FFOA&#xff09;是一种启发式优化算法&#xff0c;受果蝇觅食行为的启发。将其应用于优化BP神经网络&#xff0c;主要是为了寻找BP神经网络中的最佳权重和偏置值。以下是一个基本的流程&#xff1a; 初始化&#xff1a…

上班族小张的副业之路:下班后的水牛社赚钱故事

在快节奏的都市生活中&#xff0c;上班族小张每天忙碌于办公室与家庭之间&#xff0c;重复着朝九晚五的生活。然而&#xff0c;他内心总渴望寻找一种既能充实生活&#xff0c;又能增加收入的副业方式。直到有一天&#xff0c;他发现了水牛社——一个为他提供丰富副业资源和机会…

信息时代的智慧导航:高效搜索、信息筛选与信任构建的全面指南!

文章目录 一、高效搜索&#xff1a;快速定位目标信息的秘诀二、信息筛选&#xff1a;去伪存真&#xff0c;找到有价值的信息三、信任构建&#xff1a;深入了解与直接沟通《搜索之道&#xff1a;信息素养与终身学习的新引擎》亮点内容简介目录获取方式 随着科技的飞速发展&#…

jenkins汉化不完全问题解决

jenkins安装完Localization:Chinese(Simplified)中文语言包后&#xff0c;发现是出现汉化不完全或者部分汉化的情况&#xff0c;如下图&#xff1a; 解决方法&#xff1a; 启动命令中指定语言 -Duser.languageen_US.UTF-8 或者 -Duser.languageC.UTF-8原因分析&#xff1a;安…

网上招聘系统的设计与实现参考论文(论文 + 源码)

【免费】网上招聘系统的设计与实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89251636 网上招聘系统的设计与实现 摘 要 随着时代的发展&#xff0c;中国的互联网技术愈加成熟&#xff0c;已经有越来越多的社会群体开始学会使用互联网技术&#xff0c;整个…

STM32定时器的OC比较和PWM

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 输出比较(OC) 2. PWM 3. PWM的输出 3.1 高级定时器 3.2 通用定时器 4. PWM的输出结构 5. 代码示例 5.1 PWM.c 5.2 PWM.h 5.3 main.c 这篇文章解释了TIM定时器的内部时钟和外部时钟的使用&a…

头歌:Spark的安装与使用

第1关&#xff1a;Scala语言开发环境的部署 相关知识 Scala是一种函数式面向对象语言&#xff0c;它融汇了许多前所未有的特性&#xff0c;而同时又运行于JVM之上。随着开发者对Scala的兴趣日增&#xff0c;以及越来越多的工具支持&#xff0c;无疑Scala语言将成为你手上一件…

YOLOv9/YOLOv8算法改进【NO.128】 使用ICCV2023超轻量级且高效的动态上采样器( DySample)改进yolov8中的上采样

前 言 YOLO算法改进系列出到这&#xff0c;很多朋友问改进如何选择是最佳的&#xff0c;下面我就根据个人多年的写作发文章以及指导发文章的经验来看&#xff0c;按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通&#xff1a; 首推…