当前位置: 首页 > article >正文

C语言学习记录(16)文件操作7

前面学的东西感觉都跟写代码有关系,怎么突然就开始说文件了,有什么用呢?

其实,文件是另一种数据存储的方式,学会使用文件就可以让我们的数据持久的保存。

一、文件是什么

就算没有学过相关的知识,在这么多年不管是用电脑玩游戏,还是是学习的过程中,其实都绕不开文件:

.doc结尾的word文档,.xlsx结尾的excel文档,.txt结尾的文本文件等等。

就算上面这些都没见过,写C语言的时候,创建的.c后缀的文件,也是文件,我们就算不知道是什么,至少见过这几种。

文件一般存储在电脑的硬盘上,比如网上买的那种移动硬盘了,固态硬盘了,这里面存储的数据不管是开机关机或者断电,数据都不会丢失。

一般在程序设计中,可以分为程序文件和数据文件。

1.程序文件

程序文件一般就是我们写的源文件了(.c),或者目标文件了(windows环境后缀.obj),亦或是可执行程序(.exe)。

2.数据文件

这类文件你要让他运行起来基本就不大可能,这类文件只是存储某些数据来的,也就相当于什么呢,手机里的通讯录,备忘录,这里面的玩意纯纯是人写进去的(这个相当于往文件里写数据),并且一般也不动,最多你记录个账号密码啥的有时候就会去看看(这个就可以说是调用文件中的数据)。

之前我们的输入输出都是即时的终端进行输入输出的,说人话就是,通过键盘这个终端输入,打印到屏幕这个终端去显示。

而今天我们要学习的一系列文件有关的知识和库函数,都是针对数据文件来的。

3.文件名

一般我们说的文件名就是文件主干加后缀,如:test.c data.txt等等

但是文件名往往不会单独使用,一般要带上文件的路径:

如:c:\code\test.txt

通过路径,就方便对文件进行相关操作。

二、文件数据存储形式

我们知道,在计算机最底层只能存二进制位0和1,内存中就是以二进制的形式存储的,但是如果存到我们的外存,也就是相关文件中,可以根本不动的存入二进制位,也可以以ASCII码的形式存储。

根据在文件中的存储形式的不同可以分为:二进制文件和文本文件。

光说可能挺抽象的,画个图:

这就是区别,后面介绍库函数的时候就明白了。

三、文件的打开和关闭

一看见这,就会有人说,那还不简单,双击打开,点×就关闭。

当然是让你在程序里实现文件的打开和关闭了,因为你后续不管要对文件的数据改写了,增补了,第一步都得是打开文件,用完得关闭文件。

一直有一个冷笑话不就是这样的嘛,把一个大象放冰箱需要三步,打开冰箱,放入大象,关上冰箱。

1.流和标准流

在正式开始学习对文件操作的一系列函数前,补充学习一下什么叫做流。

我们写程序的时候可能想要往外部设备(屏幕、网络、文件等)中去输出数据,也可能从外部设备(键盘、网络、文件等)读取数据,不同的外部设备的输入输出的操作是不尽相同的,如果程序员对于每一种设备的交互都得一点一点掌握的话实在是太麻烦了,所以为了方便程序员的操作,就抽象出来了一个流的概念。

就类似于这种。

我们创建好一个C语言文件以后,其他的事什么都不用管,只需要知道怎么与流交互就行(比如我们之前学习的格式化输入输出函数:printf函数,scanf函数)。至于流和外部设备怎么交互,那就不是我们需要在意的了。

标准流

这时候就有人要问了,你说我们是跟流进行交互的,但是写的时候之前也就是用用printf函数和scanf函数,输入的时候感觉就是键盘,输出的时候就是屏幕。

那是因为C语言在开启的时候默认打开了三个流:
stdin - 标准输入流。一般都是键盘输入,scanf函数就是从标准输入流读取数据。

stdout - 标准输出流。一般都是屏幕上输出,printf函数就是输出到标准输出流。

stderr - 标准错物流。一般就输出到屏幕上。

stdin stdout stderr的类型是FILE*,一般就称为文件指针,在C语言就是通过文件指针来对流进行维护的。

2.文件指针

对于文件指针太底层的东西也没有必要去学习,比如文件指针存的是什么、系统怎么使用这些指针等,因为文件在使用的时候系统就会自动创建一个相应的文件指针,便于对文件的后续操作。

文件在使用的时候会在内存中开辟一块文件信息区,这块空间就是用来存放文件的数据,文件指针操作的也就是这样一块空间,通过对文件信息区对文件进行相关操作,即通过文件指针间接访问文件。

3.文件的打开和关闭函数

今天介绍的所有与文件操作相关的文件都在<stdio.h>这个文件中。

fopen函数

第一个参数是const char* filename,即文件名(可以包含路径),第二个参数是以什么样的方式去打开文件:        

就讲这几个方式,去打开文件

如果文件打开成功,返回一个FILE*的指针,失败则返回NULL。

例:

首先是在这个.c文件的路径下面不存在test.txt的文件,这个时候以读的形式打开文件,肯定只能失败:

创建一个再读肯定就没问题了。

fclose函数

文件有开就得有关,这样看来fopen和fclose就跟malloc(或者其他开辟动态内存的函数)和free的关系一样了。

参数也基本一致

传给我一个你上面打开的文件的指针,我就给你关了。

关成功返回0,否则返回EOF。

有借有还,有开有关。

四、文件顺序读写

接下来一对一对的介绍,因为这些两两成对的函数,参数基本相同,用法只有输入输出的区别而已。

1.fgetc和fputc函数

总得来说,这俩都是对流里面的字符进行操作,fgetc是从流里面得到字符,也就是从文件到程序,这个函数可以看作输入,fputc是往流里面写字符,也就是输出,所以为了有的读,就先往文件里写,再从文件里面读。

fputc

fputc第一个参数就是字符,因为用的时候肯定读的是ASCII码,所以是int类型变量来接收,第二个参数就是要操作的文件对应的一个FILE*的指针。

要写东西,就以写的形式打开,写前并没有这个文件,没有的话这种情况下会创建一个“test.txt”的文件,并根据循环内容,打印所有小写字母:

这里就可以看出来一点点门道,如果你要往里面写字符,FILE*肯定包含一个char*类型的指针,专门用来赋值,且char*每次赋值以后必定后移,不然就不可能出现一行都打印,最终只能展示出来个z,而不是这一串小写字母。

fgetc

进过fputc我们往文件里写了那么多东西,拿出来几个看看,参数只有FILE*的指针(操作哪个文件给他就行,不用深究),返回读取到的字符的ASCII码:

循环了五次,读的刚好就是abcde。

2.fputs和fgets函数

fputs

类比下来就是,我这里要输出字符串(再次强调,站在程序的角度往文件里写字符串就是在输出,类似于利用程序往屏幕上打印值),什么样的字符串呢?

从你给的字符串的首地址开始,一直到'\0'前,即'\0'不被包括在内。

FILE*的指针不用再解释。

实例:

还是本来没有这个文件,写的形式打开,创建以后往里写东西。

结果挺相似的,只不过这次写的是字符串。

注意,fputs可不会给你打空白字符(空格 换行等):

所以如果想写一行一行的还得手动换行。

fgets

有点细微的差别

翻译翻译就是你得给我个地方(类似于格式化输入一个值,需要给个某个变量的地址来存),一块str指向的可以存字符的内存空间,num是你期望str中到时候存几个字符(如果你想读Hello world的Hello,你看着这个是5个字符,但是存到里面应该是'Hello\0',所以读的时候就得给6,给'\0'留一个位置),FILE*不再解释。

当然,读取过程中碰见换行符或文件末尾停止读取(\n也会被读取)

读取成功返回str,读到文件末尾设置EOF标识符并返回NULL,读取错误设置ferror并返回NULL。

因为只会读num - 1个,第num个放'\0'。

如果给的num是6,刚好读完Hello;如果给的num是8,由于空格也被读,w刚好是第七个,所以输入8才能到。

3.fprintf和fscanf函数

格式化的输入输出函数,只不过是针对文件的。

这俩其实说的必要都没有:

就加了一个FILE*的指针做参数,其他完全一样,完全可以当成printf和scanf,只不过最后别忘在最前面加要操作的文件对应的指针即可。

直接一起展示了,不多bb:


以上这些讲的文件操作函数适用于所有流,剩下那俩函数只适用于文件流,但由于今天演示全部以文件形式,所以看不出来什么区别。


4.fwrite和fread函数

这两个函数都是以二进制的形式读写文件。

参数返回值都差不多,拿过来一起讲了。

void* ptr是因为要对ptr指向的那块内存空间的内容进行改写或复制,但不知道这个指针指向的空间存的什么类型的值,因此用void*来接收;

size_t的size是每读写一次读多少个字节;

size_t的count读写的次数;

FILE*这个指针不再解释。

最后返回一个成功读写的次数。

没啥可说的,参数怎么写,咱就怎么用。

五、文件随机读写

反正是学函数,不多bb

1.fseek函数

依旧参数和返回值\.

FILE*这个指针还是不用多说,用哪个文件传哪个指针;

long int的offset,其实offset我们早有了解,在前面学习的时候用过一个宏叫offsetof,当时用这个去算结构体成员变量相对于结构体起始位置的偏移量,这里的offset也是偏移量的意思,相对于谁的偏移量呢?

int的origin是一个规定好的常量,作为offset的参照物:

分别是指针起始位置、指针当前位置和文件末尾。

返回值基本没啥用。

怎么用呢?

比如我们学fgetc的时候创建的那个test.txt的文件,假如我想从里面读取ad该怎么读?

如果只是顺着读,那么必定读成abcd,因为在上面的时候验证过指针每访问一个元素后就会自动后移,如果我们自己来移动指针的话就可以实现随机读。

fseek函数就是来移动遍历文件的指针的。

提供这三种参照物就是为了方便最快找出偏移量去访问,很明显,在这里就是前两种方便,使用的时候择优。

2.ftell函数

给出文件指针即可。

算出来的是距离SEEK_SET的偏移量。

3.rewind函数

也没啥可说的,就把文件指针给他,他就给你初始化到SEEK_SET那个位置。

六、文件读取结束的判定

有两个函数是用来判断文件是因为什么原因结束的:

feof和ferror

这两个函数基本意思是完全相同的:

在读取结束以后,会有指示符。

上面讲fgetc函数的时候说了,总会有文件读取结束的时候,如果读取结束是因为碰见了文件末尾,那就设置个指示符,feof这个时候再通过文件指针去找,如果找到了这个指示符那就返回一个非0值,否则返回0;ferror同理,如果因为读取发生错误结束,也设置个指示符,ferror如果碰见了这个标识符,就会返回一个非0值,否则返回0。

这个就不再举例了。

相关文章:

C语言学习记录(16)文件操作7

前面学的东西感觉都跟写代码有关系&#xff0c;怎么突然就开始说文件了&#xff0c;有什么用呢&#xff1f; 其实&#xff0c;文件是另一种数据存储的方式&#xff0c;学会使用文件就可以让我们的数据持久的保存。 一、文件是什么 就算没有学过相关的知识&#xff0c;在这么…...

Coze平台​ 创建AI智能体的详细步骤指南

一、创建智能体的基础流程​ ​注册与登录​ 访问Coze官网&#xff08;www.coze.cn&#xff09;&#xff0c;使用邮箱或手机号注册账号并登录。 ​创建智能体​ 在控制台点击左侧“”按钮&#xff0c;选择“创建智能体”&#xff0c;输入名称&#xff08;如“职场鼓励师”&…...

《作用域大冒险:从闭包到内存泄漏的终极探索》

“爱自有天意&#xff0c;天有道自不会让有情人分离” 大家好&#xff0c;关于闭包问题其实实际上是js作用域的问题&#xff0c;那么js有几种作用域呢&#xff1f; 作用域类型关键字/场景作用域范围示例全局作用域var&#xff08;无声明&#xff09;整个程序var x 10;函数作用…...

android Stagefright框架

作为Android音视频开发人员&#xff0c;学习Stagefright框架需要结合理论、源码分析和实践验证。以下是系统化的学习路径&#xff1a; 1. 基础准备 熟悉Android多媒体体系 掌握MediaPlayer、MediaCodec、MediaExtractor等核心API的用法。 理解Android的OpenMAX IL&#xff08…...

Shell脚本-变量的分类

在Shell脚本编程中&#xff0c;变量是存储数据的基本单位。它们可以用来保存字符串、数字甚至是命令的输出结果。正确地定义和使用变量能够极大地提高脚本的灵活性与可维护性。本文将详细介绍Shell脚本中变量的不同分类及其应用场景&#xff0c;帮助你编写更高效、简洁的Shell脚…...

<C#>.NET WebAPI 的 FromBody ,FromForm ,FromServices等详细解释

在 .NET 8 Web API 中&#xff0c;[FromBody]、[FromForm]、[FromHeader]、[FromKeyedServices]、[FromQuery]、[FromRoute] 和 [FromServices] 这些都是用于绑定控制器动作方法参数的特性&#xff0c;下面为你详细解释这些特性。 1. [FromBody] 作用&#xff1a;从 HTTP 请求…...

让数据应用更简单:Streamlit与Gradio的比较与联系

在数据科学与机器学习的快速发展中&#xff0c;如何快速构建可视化应用成为了许多工程师和数据科学家的一个重要需求。Streamlit和Gradio是两款备受欢迎的开源库&#xff0c;它们各自提供了便捷的方式来构建基于Web的应用。虽然二者在功能上有许多相似之处&#xff0c;但它们的…...

LlamaIndex 生成的本地索引文件和文件夹详解

LlamaIndex 生成的本地索引文件和文件夹详解 LlamaIndex 在生成本地索引时会创建一个 storage 文件夹&#xff0c;并在其中生成多个 JSON 文件。以下是每个文件的详细解释&#xff1a; 1. storage 文件夹结构 1.1 docstore.json 功能&#xff1a;存储文档内容及其相关信息。…...

AndroidRom定制删除Settings某些菜单选项

AndroidRom定制删除Settings某些菜单选项 1.前言. 最近在Rom开发中需要隐藏设置中的某些菜单&#xff0c;launcher3中的定制开发&#xff0c;这个属于很基本的定制需求&#xff0c;和隐藏google搜素栏一样简单&#xff0c;这里我就不展开了&#xff0c;直接上代码. 2.隐藏网络…...

Mysql相关知识2:Mysql隔离级别、MVCC、锁

文章目录 MySQL的隔离级别可重复读的实现原理Mysql锁按锁的粒度分类按锁的使用方式分类按锁的状态分类 MySQL的隔离级别 在 MySQL 中&#xff0c;隔离级别定义了事务之间相互隔离的程度&#xff0c;用于控制一个事务对数据的修改在何时以及如何被其他事务可见。MySQL 支持四种…...

Python爬虫实战:获取海口最近2周天气数据,为出行做参考

一、引言 天气状况对人们的出行计划影响重大。获取准确的天气信息并进行分析,能助力用户更好地规划出行。天气网虽提供丰富的天气数据,但因网站存在反爬机制,直接获取数据存在一定难度。本研究借助 Python 的 Scrapy 框架,结合多种技术手段,实现对海口最近两周天气数据的…...

并发设计模式之双缓冲系统

双缓冲的本质是 ​​通过空间换时间​​&#xff0c;通过冗余的缓冲区解决生产者和消费者的速度差异问题&#xff0c;同时提升系统的并发性和稳定性。 双缓冲的核心优势 优势具体表现解耦生产与消费生产者和消费者可以独立工作&#xff0c;无需直接同步。提高并发性生产者和消…...

linux sysfs的使用

在Linux内核驱动开发中&#xff0c;device_create_file 和 device_remove_file 用于动态创建/删除设备的 sysfs 属性文件&#xff0c;常用于暴露设备信息或控制参数。以下是完整示例及详细说明&#xff1a; 1. 头文件引入 #include <linux/module.h> #include <linux/…...

【数据结构和算法】3. 排序算法

本文根据 数据结构和算法入门 视频记录 文章目录 1. 排序算法2. 插入排序 Insertion Sort2.1 概念2.2 具体步骤2.3 Java 实现2.4 复杂度分析 3. 快排 QuickSort3.1 概念3.2 具体步骤3.3 Java实现3.4 复杂度分析 4. 归并排序 MergeSort4.1 概念4.2 递归具体步骤4.3 Java实现4.4…...

LintCode第192题-通配符匹配

描述 给定一个字符串 s 和一个字符模式 p &#xff0c;实现一个支持 ? 和 * 的通配符匹配。匹配规则如下&#xff1a; ? 可以匹配任何单个字符。* 可以匹配任意字符串&#xff08;包括空字符串&#xff09;。 两个串完全匹配才算匹配成功。 样例 样例1 输入: "aa&q…...

redis常用的五种数据类型

redis常用的五种数据类型 文档 redis单机安装redis数据类型-位图bitmap 说明 官网操作命令指南页面&#xff1a;https://redis.io/docs/latest/commands/?nameget&groupstring 常用命令 keys *&#xff1a;查看所有键exists k1 k2&#xff1a;键存在个数type k1&…...

Linux 进程与线程间通信方式及应用分析

Linux 进程与线程间通信方式及应用分析 文章目录 Linux 进程与线程间通信方式及应用分析 1. 管道&#xff08;Pipe&#xff09;1.1 匿名管道&#xff08;Anonymous Pipe&#xff09;示例代码&#xff1a;结果&#xff1a; 1.2 命名管道&#xff08;FIFO&#xff09;示例代码&am…...

AI日报 - 2024年04月22日

&#x1f31f; 今日概览(60秒速览) ▎&#x1f916; 模型进展 | Google发布Gemini 2.5 Flash&#xff0c;强调低延迟与成本效益&#xff1b;Kling AI 2.0展示多轴运动视频生成&#xff1b;研究揭示SLM在知识图谱上优于LLM&#xff0c;RLHF在推理提升上存局限。 ▎&#x1f4bc;…...

FreeRTos学习记录--2.内存管理

后续的章节涉及这些内核对象&#xff1a;task、queue、semaphores和event group等。为了让FreeRTOS更容易使用&#xff0c;这些内核对象一般都是动态分配&#xff1a;用到时分配&#xff0c;不使用时释放。使用内存的动态管理功能&#xff0c;简化了程序设计&#xff1a;不再需…...

HAL库(STM32CubeMX)——高级ADC学习、HRTIM(STM32G474RBT6)

系列文章目录 文章目录 系列文章目录前言存在的问题HRTIMcubemx配置前言 对cubemx的ADC的设置进行补充 ADCs_Common_Settings Mode:ADC 模式 Independent mod 独立 ADC 模式,当使用一个 ADC 时是独立模式,使用两个 ADC 时是双模式,在双模式下还有很多细分模式可选 ADC_Se…...

单例模式(线程安全)

1.什么是单例模式 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有单…...

FreeRTos学习记录--1.工程创建与源码概述

1.工程创建与源码概述 1.1 工程创建 使用STM32CubeMX&#xff0c;可以手工添加任务、队列、信号量、互斥锁、定时器等等。但是本课程不想严重依赖STM32CubeMX&#xff0c;所以不会使用STM32CubeMX来添加这些对象&#xff0c;而是手写代码来使用这些对象。 使用STM32CubeMX时&…...

基于大模型的血栓性外痔全流程风险预测与治疗管理研究报告

目录 一、引言 1.1 研究背景与目的 1.2 研究意义 二、血栓性外痔概述 2.1 定义与发病机制 2.2 临床表现与诊断方法 2.3 现有治疗手段综述 三、大模型在血栓性外痔预测中的应用原理 3.1 大模型技术简介 3.2 模型构建与训练数据来源 3.3 模型预测血栓性外痔的工作流程…...

进程控制(linux+C/C++)

目录 进程创建 写时拷贝 fork 进程终止 退出码 进程退出三种情况对应退出信号 &#xff1a;退出码&#xff1a; 进程退出方法 进程等待 两种方式 阻塞等待和非阻塞等待 小知识 进程创建 1.在未创建子进程时&#xff0c;父进程页表对于数据权限为读写&#xff0c;对于…...

C++如何处理多线程环境下的异常?如何确保资源在异常情况下也能正确释放

多线程编程的基本概念与挑战 多线程编程的核心思想是将程序的执行划分为多个并行运行的线程&#xff0c;每个线程可以独立处理任务&#xff0c;从而充分利用多核处理器的性能优势。在C中&#xff0c;开发者可以通过std::thread创建线程&#xff0c;并使用同步原语如std::mutex、…...

TensorBoard如何在同一图表中绘制多个线条

1. 使用不同的日志目录 TensorBoard 会根据日志文件所在的目录来区分不同的运行。可以为每次运行指定一个独立的日志目录&#xff0c;TensorBoard 会自动将这些目录中的数据加载并显示为不同的运行。 示例&#xff08;TensorFlow&#xff09;&#xff1a; import tensorflow…...

微软Entra新安全功能引发大规模账户锁定事件

误报触发大规模锁定 多家机构的Windows管理员报告称&#xff0c;微软Entra ID新推出的"MACE"&#xff08;泄露凭证检测应用&#xff09;功能在部署过程中产生大量误报&#xff0c;导致用户账户被大规模锁定。这些警报和锁定始于昨夜&#xff0c;部分管理员认为属于误…...

基于FPGA的一维时间序列idct变换verilog实现,包含testbench和matlab辅助验证程序

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 DCT离散余弦变换 4.2 IDCT逆离散余弦变换 4.3 树结构实现1024点IDCT的原理 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) matlab仿真结果 FPGA仿真结果 由于FP…...

Linux进程5-进程通信常见的几种方式、信号概述及分类、kill函数及命令、语法介绍

目录 1.进程间通信概述 1.1进程通信的主要方式 1.2进程通信的核心对比 2.信号 2.1 信号的概述 2.1.1 信号的概念 2.2信号的核心特性 2.3信号的产生来源 2.4信号的处理流程 2.5关键系统调用与函数 2.6常见信号的分类及说明 2.6.1. 标准信号&#xff08;Standard Sig…...

[架构之美]一键服务管理大师:Ubuntu智能服务停止与清理脚本深度解析

[架构之美]一键服务管理大师&#xff1a;Ubuntu智能服务停止与清理脚本深度解析 服务展示&#xff1a; 运行脚本&#xff1a; 剩余服务&#xff1a; 一、脚本设计背景与核心价值 在Linux服务器运维中&#xff0c;服务管理是日常操作的重要环节。本文介绍的智能服务管理脚本&a…...