【落羽的落羽 C语言篇】文件操作
文章目录
- 一、文件的概念和分类
- 1. 概念和分类
- 2. 文件名
- 3. 数据文件
- 三、文件操作
- 1. 文件的打开和关闭
- 1.1 流
- 1.2 文件指针
- 1.3 文件的打开和关闭
- 2. 文件的顺序读写
- 3. 文件的随机读写
- 4. 文件读取的判定
- 5. 文件缓冲区
一、文件的概念和分类
1. 概念和分类
文件是用来保存数据的。如果没有文件,我们写的程序会直接存储在电脑内存中,如果程序退出,内存被释放回收,数据就丢失了。所以如果要将数据进行持久化的保存,我们就可以使用文件来保存数据。
在生活中,我们一般直接将电脑磁盘中的文件称之为文件。而在程序设计中,我们所说的文件一般分为两种:程序文件、数据文件。
- 程序文件包括:源程序文件(后缀为.c)、目标文件(Windows环境下后缀为.obj)、可执行程序(后缀为.exe)以后会再次介绍的。
- 数据文件的内容,是程序运行时读写的数据,包括程序运行时需要从中读取数据的文件,或者输出内容的文件。
在之前C语言的学习过程中,我们对数据的输出输入都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。但有时候我们也需要把数据输出到磁盘中,也需要从磁盘中读取数据到内存中来使用,这时就是对磁盘里的文件进行文件操作了。
2. 文件名
我们还要知道的是:一个文件通常要有一个唯一的文件标识以便于使用者识别和引用,这就是文件名,通常包含“文件路径、文件名主干、文件后缀”三部分。
举个例子,在我的电脑磁盘中有:
右键点击复制文件地址,能得到这个文件的文件名是:
D:\ACG电吉\春日影\Final春日影 吉他.pdf
其中,这个文件本身的名字“Final春日影 吉他”,是文件名主干。
前面的“D:\ACG电吉\春日影\”,是文件路径。
最后的“.pdf”,是文件后缀。
很简单对吧。
3. 数据文件
数据文件还可以再分为文本文件和二进制文件。
- 文本文件:数据以ASCII值的形式存储的文件
- 二进制文件:数据以二进制的形式存储的文件
字符型数据一律用ASCII值形式存储,数值型数据既可以用ASCII值形式存储也可以用二进制形式存储。
它们的区别是什么呢?举个栗子,整数12345
- 如果以ASCII形值式输出到磁盘中,则占用五个字节(一个字符占据一个字节),内容是00110001 00110010 00110011 00110100 00110101(即ASCII值49、50、51、52、53,对应字符“1”、“2”、“3”、“4”、“5”)
- 如果以二进制形式输出到磁盘中,则占用四个字节(int大小),内容是00000000 00000000 00110000 00111001(就是12345的二进制表示)
三、文件操作
1. 文件的打开和关闭
1.1 流
流是计算机领域一个抽象但重要的概念。
简单来说,程序需要跟各种外部设备交互,外部设备包括键盘、显示器、磁盘、U盘、网络等等,程序的数据需要输出到各种外部设备上,也需要从各种外部设备获取数据,不同的外部设备的输入输出操作各不相同。为了方便程序员对各种设备的操作,人们抽象出了“流”的概念。“流”就像一条流淌着数据的河,程序和外部设备将数据都投入这条“河”中,或者各取所需的数据。C语言内部处理好外部设备和流的数据传递,而程序设计者只要再考虑程序如何与流交互就好了。
一般情况下,我们想要往流里写数据,或者从流里读取数据,都是先打开流,然后再操作。
那么,为什么我们以前写C语言程序,从键盘上读取数据,向屏幕上输出数据,并没有打开流的操作呢?这是因为C语言程序在启动时,默认会打开三个流:
- stdin(标准输入流):它在大多数环境下能从键盘输入数据,scanf函数就是从这个流中读取数据的
- stdout(标准输出流):它在大多数环境下能输出数据至显示器界面,printf函数就是将信息输出到这个流中的
- stderr(标准错误流):它在大多数环境下能输出数据至显示器界面
这三个流的类型是FILE*
,被称为文件指针。在C语言中,就是通过文件指针来维护流的各种操作的。
1.2 文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息,比如文件的名字、状态、位置等等。这些信息被保存在一个结构体变量中,该结构体变量是由系统声明的,被typedef重命名为FILE。不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。
使用者打开一个文件时,系统会根据文件的情况自动创建一个FILE类型的变量,自动填充好内部信息,使用者不必关心具体细节。
为了维护这个FILE结构的变量,一般使用FILE*类型的指针,这就是文件指针。比如,定义一个FILE* pf;
可以使pf指向某个文件的文件信息区,通过该文件信息区的信息来操作该文件,换句话说,通过文还指针能够间接找到与它相关联的文件。
1.3 文件的打开和关闭
读写文件之前应该先打开文件,使用后应该关闭文件。ANSI C规定使用fopen函数打开文件,fclose函数关闭文件。它们(和以下函数)包括在头文件stdio.h中
fclose的使用方式很简单,参数就是需要关闭的文件的文件指针。
fopen的使用较为复杂:
FILE* fopen(const char* filename, const char* mode);
它的返回值是打开的文件的文件指针。
它的第一个参数是文件名,第二个参数是文件的打开模式,有以下模式及其作用:
文件打开模式 | 含义 | 如果指定文件不存在 |
---|---|---|
r(只读) | 为了输入数据,打开一个文本文件 | 返回空指针 |
w(只写) | 为了输出数据,打开一个文本文件 | 创建一个新的文件(如果文件存在,会清空原内容) |
a(追加) | 向文本文件尾添加数据 | 创建一个新的文件 |
rb(只读) | 为了输入数据,打开一个二进制文件 | 返回空指针 |
wb(只写) | 为了输出数据,打开一个二进制文件 | 创建一个新的文件 |
ab(追加) | 向二进制文件尾添加数据 | 创建一个新的文件 |
r+(读写) | 为了读写数据,打开一个文本文件 | 返回空指针 |
w+(读写) | 为了读写数据,打开一个文本文件 | 创建一个新的文件 |
a+(读写) | 在文本文件尾读写数据 | 创建一个新的文件 |
rb+(读写) | 为了读写数据,打开一个二进制文件 | 返回空指针 |
wb+(读写) | 为了读写数据,创建一个二进制文件 | 创建一个新的文件 |
ab+(读写) | 在二进制文件尾读写数据 | 创建一个新的文件 |
举例,一开始我的项目文件夹里没有data.txt这个文件
如果有FILE* pf = fopen("data.txt","r");
:
如果是FILE* pf = fopen("data.txt","w");
就会在这个代码项目的文件夹中创建这样一个文件:
当然,我们还可能需要从电脑的其他磁盘上的其他文件中读写数据,就需要明白绝对路径和相对路径的表示方法:
- 绝对路径就是一个文件的完整文件名,比如之前提到过的 D:\ACG电吉\春日影\Final春日影 吉他.pdf
- 相对路径要用
.
或..
表示,.
表示当前路径,..
表示上一级路径。每一级中间本来需要用\
分割,但在C语言中需要被转义,即要用转义字符\\
表示\
举个栗子,我的电脑中一开始没有data.txt这个文件,我的C语言程序源文件位置如下:
如果在程序中以w模式打开一个D盘文件data.txt,就会自动创建
- 用绝对路径表示:
fopen("D:\\data.txt","w");
- 用相对路径表示:
fopen(".\\..\\..\\..\\..\\data.txt","w");
都是成功的
2. 文件的顺序读写
文件的顺序读写涉及到一系列函数:
函数 | 功能 | 适用于 |
---|---|---|
fgetc | 字符输入 | 所有输入流 |
fputc | 字符输出 | 所有输出流 |
fgets | 按文本行输入 | 所有输入流 |
fputs | 按文本行输出 | 所有输出流 |
fscanf | 格式化输入 | 所有输入流 |
fprintf | 格式化输出 | 所有输出流 |
fread | 二进制输入 | 文件输入流 |
fwrite | 二进制输出 | 文件输出流 |
这些函数的使用大同小异,我们就举两个例子,其余大家自己查阅了解即可
fputs函数的第一个参数是要写入的字符串,第二个参数是要写进的文件
fgetc函数的参数是要从中读取字符的文件
#include<stdio.h>
int main()
{FILE* pf = NULL;pf = fopen("data.txt", "w");fputs("TECH OTAKUS SAVE THE WORLD", pf);fclose(pf);pf = fopen("data.txt", "r");int n = 0;while(n++ < 5)printf("%c\n", fgetc(pf));fclose(pf);return 0;
}
结果很显然,程序创建了一个文本文件写入了一些内容,然后打印出前四个字符。
3. 文件的随机读写
上面的函数只能对文件内容按顺序读写,有时我们也需要对内容按照特定顺序读写,这就是文件的随机读写。要用到以下函数:
-
fseek
这个函数能改变文件光标的位置,“文件光标”就是读写数据的位置,可以理解成我们在电脑手机上打字的这个光标。
第一个参数是文件指针,第二个参数是你想要的偏移量,第三个参数是你想从哪个位置计算偏移量。第三个参数是有三个取值的:
SEEK_SET是文件的开头,SEEK_CUR是当前光标的位置,SEEK_END是文件的末尾。
光标位置是怎么决定的呢?比如文件指针pf刚刚进行了写数据,其指向的文件里刚写下了abcdef
,此时光标在末尾,即f
后的位置。如果有fseek(pf, 2, SEEK_SET);
光标在文本开头后偏移2个位置,即b和c中间。假如我们再写一次数据,就会从这里开始写,新写入的数据会覆盖掉刚才的几个字符:偏移量负值代表左偏移,正值代表右偏移。所以,对于
abcdef
,fseek(pf, 2, SEEK_SET)
和fseek(pf, -4, SEEK_END)
的效果其实是一样的再举例一个用法,fgetc读取字符是从文件开头向后一个一个读的。因为光标起始位置是开头,每次读光标之后的一个字符,然后光标向右偏移1。但我们不想按这样的顺序读数据时,就可以用fseek函数实时调整光标的位置了。
-
ftell
很简单,它的参数是文件指针,这个函数能返回这个文件中当前光标相对于开头的偏移量
-
rewind
这个函数能让参数文件的光标返回起始位置
4. 文件读取的判定
不同的函数读取到文件末尾时的标识不一样,比如fgets读取结束会返回NULL,fgetc读取结束会返回EOF,等等。对于二进制文件,fread的返回值小于实际要读取的个数,说明读取结束
5. 文件缓冲区
最后一个简单的知识点:ASNI C标准采用“缓冲文件系统”处理数据文件,它指系统自动在内存中为程序每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据,会先送到文件缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机输入数据,则从磁盘文件中读取数据输入到内存缓冲区,然后再从缓冲区逐个地将数据送到程序数据区。缓冲区的大小由C编译系统决定。因为由缓冲区的存在,所以C语言在进行文件操作时,需要刷新缓冲区或者结束时关闭文件。如果不做,可能有读写文件的问题。
本篇完,感谢阅读~
相关文章:

【落羽的落羽 C语言篇】文件操作
文章目录 一、文件的概念和分类1. 概念和分类2. 文件名3. 数据文件 三、文件操作1. 文件的打开和关闭1.1 流1.2 文件指针1.3 文件的打开和关闭 2. 文件的顺序读写3. 文件的随机读写4. 文件读取的判定5. 文件缓冲区 一、文件的概念和分类 1. 概念和分类 文件是用来保存数据的。…...

RNN之:LSTM 长短期记忆模型-结构-理论详解-及实战(Matlab向)
0.前言 递归!循环神经网络Recurrent Neural Network 循环神经网络(又称递归神经网络,Recurrent Neural Network,RNN)。是一种用于处理序列数据的神经网络结构,具有记忆功能,能够捕捉序列中的时…...

战略与规划方法——深入解析波士顿矩阵(BCG Matrix):分析产品组合的关键工具
深入解析波士顿矩阵(BCG Matrix):分析产品组合的关键工具 在现代商业管理中,合理地分析和管理产品组合对于企业的成功至关重要。波士顿矩阵(BCG Matrix),又称为成长份额矩阵,是一种由波士顿咨询集团(Boston Consulting Group)在20世纪70年代提出的战略工具,用于帮助…...

【记录52】el-table-column 添加fixed属性 滚动条无法滑动
问题: el-table-column 添加fixed属性 滚动条无法滑动 使用element UI组件,用到el-table的el-table-column的fixed属性时,当滚动条长度小于固定列时,滚动条无法通过鼠标去点击滑动操作 原因 fixed是用来固定列的属性,其…...

晨辉面试抽签和评分管理系统之十:如何搭建自己的数据库服务器,使用本软件的网络版
晨辉面试抽签和评分管理系统(下载地址:www.chenhuisoft.cn)是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…...

主链和Layer2之间资产转移
主链和Layer2之间资产转移 主链和Layer2之间资产转移是实现Layer2技术的关键环节,以下是资产转移的流程、流行解决方案及原理: 资产从主链转移到Layer2 用户在主链上发起一笔交易,将资产发送到一个特定的智能合约地址,这个合约是主链与Layer2之间的桥梁。智能合约会锁定用…...

麒麟操作系统服务架构保姆级教程(十)rewrite跳转
如果你想拥有你从未拥有过的东西,那么你必须去做你从未做过的事情 我们访问一个网页的时候会遇到一些奇形怪状的url地址,想优化一下,看着顺眼一点,或者打开一个短视频软件想摸鱼刷一会视频,在打开界面的时候无意间按到…...

MySQL表的创建实验
创建并使用数据库mydb6_product 。 mysql> create database mydb6_product; Query OK, 1 row affected (0.01 sec)mysql> use mydb6_product; Database changed 新建employees表。 对于gender,有默认值意味着不为空,在建表时可以选择不写not nul…...

【高可用自动化体系】自动化体系
架构设计的愿景就是高可用、高性能、高扩展、高效率。为了实现架构设计四高愿景,需要实现自动化系统目标: 标准化。 流程自助化。 可视化:可观测系统各项指标、包括全链路跟踪。 自动化:ci/cd 自动化部署。 精细化:…...

总结SpringBoot项目中读取resource目录下的文件多种方法
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目…...

Java-KMP字符串匹配算法
给两个字符串s和t,如何很快的知道s是否包含t(即t是否是s的子串)。暴力的方法,我们依次以s每个位置为头,去匹配t。 public int find(String s, String t) {char[] ss s.toCharArray();char[] tt t.toCharArray();int …...

Vue3使用vue-count-to数字滚动模块报错解决方案
小伙伴们是不是遇到了vue3项目使用vue-count-to出现报错的问题 报错如下: TypeError: Cannot read properties of undefined (reading _c) 这个错误信息具体是说没读取到_c的属性 具体不清楚是什么原因,排查还得去看源码,所以我们来解决&a…...

【高阶数据结构】线段树加乘(维护序列)详细解释乘与加懒标记
文章目录 1.题目[AHOI2009] 维护序列 2.懒标记处理先加后乘的形式1. 先加后乘的操作 先乘后加的形式2. 先乘后加的操作**乘法操作****加法操作** 懒标记的下传 3.代码 1.题目 题目来源:https://www.luogu.com.cn/problem/P2023 [AHOI2009] 维护序列 题目背景 老师交给小可可…...

replaceState和vue的router.replace删除query参数的区别
使用history.replaceState /*** 替换当前的 history state和url* param {(searchParams:URLSearchParams)>any} cb*/ export const replaceUrlSearch (cb) > {// 获取当前 URLconst url new URL(window.location.href)// 获取 URL 的查询参数const searchParams new …...

[USACO14JAN] Ski Course Rating G
题目大意 滑雪场用一个 N ∗ M N*M N∗M 的整数矩阵表示海拔高度,每个整数表示一个范围在 1 0 9 10^9 109 的高度。每个格子都可以滑到相邻的格子,爱好者们将会在雪场种尽情享受。有些格子被指定为起点,每个起点都要进行评级以帮助爱好者选…...

初步认识 Neo4j 图数据库
Neo4j 是一种高性能的图数据库管理系统,基于图论设计,能够高效地存储和查询复杂的关系数据。以下是关于 Neo4j 的详细介绍: 核心特性 数据模型: Neo4j 使用图数据模型,将数据以节点(Node)、关系…...

Qt中容器 QVector、QList、QSet和QMap 性能与用途比较
表格汇总: 容器存储结构随机访问性能插入/删除性能主要用途QVector连续存储的动态数组 O ( 1 ) O(1) O(1)末尾: O ( 1 ) O(1) O(1),中间: O ( n ) O(n) O(n)频繁随机访问,末尾元素的添加/删除QList优化存储࿰…...

ASP.NET Core - 依赖注入(四)
ASP.NET Core - 依赖注入(四) 4. ASP.NET Core默认服务5. 依赖注入配置变形 4. ASP.NET Core默认服务 之前讲了中间件,实际上一个中间件要正常进行工作,通常需要许多的服务配合进行,而中间件中的服务自然也是通过 Ioc…...
数学用语中 up to 的含义
1. 问题 在数学用语中,常见到“up to”这种用法, 但这种用法与我们常规情况下的用法不同,常令人困惑。 2. “等价关系”说明 已知两个数学对象 a 和 b,以及实数域R, • 当 a 和 b是通过 R 关联的࿰…...

Spring Boot + MyBatis-Flex 配置 ProxySQL 的完整指南
✅ Spring Boot MyBatis-Flex 配置 ProxySQL 的完整指南 下面是一个详细的教程,指导您如何在 Spring Boot 项目中使用 MyBatis-Flex 配置 ProxySQL 进行 读写分离 和 主从同步 的数据库访问。 🎯 目标 在 Spring Boot 中连接 ProxySQL。使用 MyBatis-…...

WEB攻防-通用漏洞_XSS跨站_权限维持_捆绑钓鱼_浏览器漏洞
目录 XSS的分类 XSS跨站-后台植入Cookie&表单劫持 【例1】:利用beef或xss平台实时监控Cookie等凭据实现权限维持 【例2】:XSS-Flash钓鱼配合MSF捆绑上线 【例3】:XSS-浏览器网马配合MSF访问上线 XSS的分类 反射型(非持久…...

人工智能任务20-利用LSTM和Attention机制相结合模型在交通流量预测中的应用
大家好,我是微学AI,今天给大家介绍一下人工智能任务20-利用LSTM和Attention机制相结合模型在交通流量预测中的应用。交通流量预测在现代城市交通管理中是至关重要的一环,它对优化交通资源分配以及提升道路通行效率有着不可忽视的意义。在实际…...

Day04-后端Web基础——Maven基础
目录 Maven课程内容1. Maven初识1.1 什么是Maven?1.2 Maven的作用1.2.1 依赖管理1.2.2 项目构建1.2.3 统一项目结构 2. Maven概述2.1 Maven介绍2.2 Maven模型2.2.1 构建生命周期/阶段(Build lifecycle & phases)2.2.2 项目对象模型 (Project Object Model)2.2.3 依赖管理模…...

Hive SQL必刷练习题:留存率问题
首次登录算作当天新增,第二天也登录了算作一日留存。可以理解为,在10月1号登陆了。在10月2号也登陆了,那这个人就可以算是在1号留存 今日留存率 (今日登录且明天也登录的用户数) / 今日登录的总用户数 * 100% 解决思…...

虚拟同步机(VSG)Matlab/Simulink仿真模型
虚拟同步机控制作为原先博文更新的重点内容,我将在原博客的基础上,再结合近几年的研究热点对其内容进行更新。Ps:VSG相关控制方向的simulink仿真模型基本上都搭建出来了,一些重要的控制算法也完成了实验验证。 现在搭建出来的虚拟…...

单头注意力机制(SHSA)详解
定义与原理 单头注意力机制是Transformer模型中的核心组件之一,它通过模拟人类注意力选择的过程,在复杂的输入序列中识别和聚焦关键信息。这种方法不仅提高了模型的性能,还增强了其解释性,使我们能够洞察模型决策的原因。 单头注意力机制的工作流程主要包括以下几个步骤:…...

【漏洞分析】DDOS攻防分析
0x00 UDP攻击实例 2013年12月30日,网游界发生了一起“追杀”事件。事件的主角是PhantmL0rd(这名字一看就是个玩家)和黑客组织DERP Trolling。 PhantomL0rd,人称“鬼王”,本名James Varga,某专业游戏小组的…...

JavaScript动态渲染页面爬取之Splash
Splash是一个 JavaScript渲染服务,是一个含有 HTTP API的轻量级浏览器,它还对接了 Python 中的 Twisted 库和 OT库。利用它,同样可以爬取动态渲染的页面。 功能介绍 利用 Splash,可以实现如下功能: 异步处理多个网页的渲染过程:获取渲染后…...

慧集通(DataLinkX)iPaaS集成平台-系统管理之UI库管理、流程模板
UI库管理 UI库管理分为平台级和自建两种,其中平台级就是慧集通平台自己内置的一些ui库所有客户均可调用,自建则是平台支持使用者自己根据规则自己新增对应的UI库。具体界面如下: 自建UI库新增界面: 注:平台级UI库不支…...

OpenCV相机标定与3D重建(59)用于立体相机标定的函数stereoCalibrate()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 标定立体相机设置。此函数找到两个相机各自的内参以及两个相机之间的外参。 cv::stereoCalibrate 是 OpenCV 中用于立体相机标定的函数。它通过一…...