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

⽂件操作详解

⽬录
一    文件操作的引入
           1   为什么使⽤⽂件?
           2   什么是⽂件?
           3   文件分类(1 从⽂件功能的⻆度来分类:程序⽂件/数据⽂件 2根据数据的组织形式:为⽂本⽂件/⼆进制⽂件)
二    ⽂件的打开和关闭
           1     流和标准流(其中标准流在C语⾔程序启动的时候,默认打开)
           2    ⽂件指针(⽂件类型指针)
           3    ⽂件的打开和关闭
三    ⽂件的顺序读写
            1   fgect函数
            2   fputc函数
            3   fgets函数
            4   fputs函数
            5   fscanf函数
            6   fprintf函数
            7   fread函数
            8   fwrite函数
              
四    ⽂件的随机读写
             1  fseek函数
             2  ftell函数
             3  rewind函数
五    ⽂件读取结束的判定
             1  ⽂本⽂件读取是否结束/⼆进制⽂件的读取结束判断
             2  ⽂本⽂件的例⼦:
             3   ⼆进制⽂件的例⼦:
六    ⽂件缓冲区

一    文件操作的引入

1   为什么使⽤⽂件?

     为了将数据进⾏持久化的保存,如果我们没有文件我们写的程序的数据其实是存储在电脑的内存中,当我们程序一退出,内存回收,数据就会丢失,等再次运⾏程序,就看不到上次程序的数据。

2   什么是⽂件?

2.1  概念:磁盘(硬盘)上的⽂件是⽂件。

2.2 ⽂件名
⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤
⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀
例如: c:\code\test.txt
为了⽅便起⻅,⽂件标识常被称为⽂件名

2.3路径的两种形式(相当路径/绝对路径)

 

3 文件分类(1 从⽂件功能的⻆度来分类:程序⽂件/数据⽂件 2根据数据的组织形式:为⽂本⽂件/⼆进制⽂件)
3.1   从⽂件功能的⻆度来分类:
程序⽂件: 程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows环境后缀为.exe)。
数据⽂件 程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。
3.2  根据数据的组织形式
⼆进制⽂件:数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存的⽂件中,就是⼆进制⽂件。
⽂本⽂件:如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂本⽂件

二     ⽂件的打开和关闭

  1   流和标准流(其中标准流在C语⾔程序启动的时候,默认打开)

1.1  流:因为不同的外部设备的输⼊输出操作各不相同,此时为了⽅便程序员对各种设备进⾏⽅便的操作便引出了流,其实,流就是为了⽅便程序员对各种设备读取数据或者输出数据的操作,而抽象出的概念,这里我们可以把流想象成流淌着字符的河。

1.2标准流的引入

在C语言中我们如何对针对⽂件、画⾯、键盘等的数据输⼊输出操作呢?其实C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。那为什么我们使用scanf和printf函数并没有直观的感觉到呢?这时候就要引入标准流。

1.3 标准流

C语⾔程序在启动的时候,默认打开了3个流:
stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
stdout - 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯。
stdin、stdout、stderr 三个流的类型是: FILE * ,通常称为⽂件指针
 
2   ⽂件指针(⽂件类型指针)

2.1  概念:

C语⾔中,我们就是通过 FILE* 的⽂件指针来维护流的各种操作的。我们在对文件进行操作时必须使用FILE*指针。 每个被使⽤的⽂件都在内存开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名 FILE。不同的C编译器的FILE类型包含的内容不完全相同,但是⼤同⼩异。

2.2 创建⼀个FILE*的指针变量

int main()

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

return 0

}

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

3    ⽂件的打开和关闭
3.1   ⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。所以我们使用文件的固定步骤打开⽂件、文件操作、关闭⽂件。这些过程需要FILE*的指针变量来连接,其实我们在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也就相当于建⽴了指针和⽂件的关系。而ANSI C 规定使⽤ fopen 函数来打开⽂件, fclose函数来关闭⽂件。

3.2使用文件的固定步骤

 fopen 函数原型:

 fclose函数原型:

3.3   文件的打开模式

其中常用的只要几个。

1

三    ⽂件的顺序读写

下面我们来介绍几个顺序读写函数,我们可以利用这几个顺序读写函数在结和文件的打开模式对文件进行操作。

顺序读写函数:

1   fgect函数

1.1  这是一个字符输入函数个,适用于所有输入流。

示例:

这里我们运用"r"只读的方式打开文件,这里我们是进行字符的读取,所以我们应在相应文件中放上内容  再看相应文件中的内容:

再看运行结果:

注意在读取字符时它会从第一个字符的位置开始读取,当每次读取完成后,光标会往后移动一位,利用这一特性,再利用循环进行读取,这样我们就可以达到像读取字符串一样,当我们想读取的个数比读取文件中的个数多会发生什么呢?这时候多余的会打印出错误信息(这里我就不举例了,感兴趣的可以自己试一试。特别注意fgetc在遇到空格时会选择跳过

 1.2    这个函数适用于使用输入流,那意味着对于标准流也有用。

这里我们先输入一个字符便可以打印出相应的字符

2   fputc函数

2.1 这是一个字符输出函数,适用于所有输出流。

示例:

现在我们打开文件观察其运行结果:

这里我们发现文件中已经有了相应的字符,但是我们·发现文件中的字符全部都在一行这是为什么呢?其实fputc函数也能识别”\0"只要其识别到”\0"结束标识符时才会换行。那这里有一个问题很值得我们思考,上面的fgect函数适用于使用输入流,是一个字符输入函数,而fputc函数这个函数适用于使用输出流,是一个字符输出函数。那么这两个函数是否呢结和使用呢?

fgect函数和fputc函数结和使用:

这里我们发现fgect函数和fputc函数结和使用结果是不行的,因为"w"模式是写入模式,会清空文件内容,在写入之后,在进行读取操作不会得到任何内容。

2.2 这个函数适用于使用输出流,那意味着对于标准流也有用。

3   fgets函数

这是一个文本行输入函数,适用于所有输入流。(文本行即能对一行操作)

这个函数有三个参数分别是存放读取字符串的地址、读取的字符个数、文件指针。

示例:

我们看一看文件中都内容:

 4  fputs函数

这是一个文本行输出函数,适用于所有输出流。(文本行即能对一行操作)

这个函数有两个参数分别是:字符串地址和文件指针

示例1:

结果:

示例2:

结果:
我们来比较一下上面两个代码运行结果我们观察看到输入的字符相同只是一个有换行一个没有,对应的结果便是有换行的结果在文件在分为两行没有换行的则在一行,所以 fputs函数是会识别换行符"\n"要想结果换行使用fputs函数就必须包含换行符。
5   fscanf函数

这是一个格式化输⼊函数函数,适用于所有输入流(格式化即特定的格式可以包含多个类型)

  我们发现这个函数的原型有些神奇,他的参数里面居然有个省略号!也就是说,它支持传入的参数个数是无限制的!要想熟练使用fscanf函数就得仿造scanf函数它们只相差一个参数fscanf函数比scanf函数多了一个文件指针。

示例:

文件内容:

运行结果:

6  fprintf函数

这是一个格式化输出函数,适用于所有输出流(格式化即特定的格式可以包含多个类型)

它的使用可以类比于printf函数比printf函数多了一个参数( 文件指针)

示例:

7   fread函数

这是一个⼆进制输⼊函数,适用于文件输入流。

这个函数传入的参数就相对来说复杂了一些:分别是存放字符串的地址、数据的字节大小、数据的数量、文件指针。

示例:

8 fwrite函数

 这是一个⼆进制输出函数,适用于文件输出流。

示例:

四    ⽂件的随机读写

1  fseek函数
这个函数可以根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)
int fseek ( FILE * stream, long int offset, int origin );

   第一个参数就是文件指针,没什么好说的,通过上前面的学习我们发现这种文件操作函数基本都要输入文件指针。

  第二个参数是偏移量参数,可以为正数,也可以为负数。

  第三个参数是起始位置

C语言为我们提供了 三个起始位置:
  • 文件头 SEEK_SET 0
  • 当前位置 SEEK_CUR 1
  • 文件尾 SEEK_END 2

2    ftell函数

 这个函数可以返回文件指针相对于起始位置的偏移量

long int ftell ( FILE * stream );

我们直接传文件指针就行,他会返回光标位置相较于文本最开始的偏移量 

rewind函数

这个函数可以让文件指针的位置回到文件的起始位置。

void rewind ( FILE * stream );

示例:

五    ⽂件读取结束的判定  

1⽂本⽂件读取是否结束/⼆进制⽂件的读取结束判断

我们都知道,EOF是文件结束的标志,那么feof呢?

  牢记:在⽂件读取过程中,不能⽤ feof 函数的返回值直接来判断⽂件的是否结束。 feof 的作⽤是:当⽂件读取结束的时候,判断读取结束的原因是否是:遇到⽂件尾结束。
⽂本⽂件读取是否结束:
判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
•fgetc 判断是否为 EOF .
•fgets 判断返回值是否为 NULL .
⼆进制⽂件的读取结束判断:
判断返回值是否⼩于实际要读的个数。
fread判断返回值是否⼩于实际要读的个数。

⽂本⽂件的例⼦:

3   ⼆进制⽂件的例⼦:

运行结果:

    ⽂件缓冲区

缓冲⽂件系统是指系统⾃动地在内存中为程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。在C语言文件操作时,其实我们读取文件内容和输入内容到文件时,并不是直接对其进行操作的,而是通过文件缓冲区操作。那为什么会有⽂件缓冲区呢?其目的是为了提高编程效率假如没有⽂件缓冲区,这是我们要对一个字符串操作时如果没有⽂件缓冲区,我们就要不断对每个字符重复的进行操作,如果有了⽂件缓冲区我们把像输入的字符一个一个先放入缓冲区,等到积攒到了一定的数量,超过缓冲区范围,再把缓冲区的字符一次性放到硬盘中,这样就能减少系统的运行压力。记住缓冲区的⼤⼩根据C编译系统决定的。

本篇文章就到此结束,欢迎大家订阅我的专栏,欢迎大家指正,希望有所能帮到读者更好了解⽂件操作相关知识 ,觉得有帮助的还请三联支持一下~后续会不断更新C/C++相关知识,我们下期再见。


http://www.mrgr.cn/news/78659.html

相关文章:

  • 计算机毕业设计Python+LSTM天气预测系统 AI大模型问答 vue.js 可视化大屏 机器学习 深度学习 Hadoop Spark
  • 【初阶数据结构和算法】二叉树顺序结构---堆的定义与实现(附源码)
  • 《通俗易懂 · JSqlParser 解析和构造SQL》
  • 百度智能云千帆大模型平台引领企业创新增长
  • Linux宝塔部署wordpress网站更换服务器IP后无法访问管理后台和打开网站页面显示错乱
  • 卸载snap docker一直卡住:Save data of snap “docker“ in automatic snapshot set #3
  • Day1 生信新手笔记
  • 如何估算自然对流传热系数
  • [GKCTF 2021]签到
  • 四:工具、环境准备-compute node
  • 七:仪表盘安装-controller node
  • OpenMP出现Stack Overflow及其疑问
  • Kubernetes——part11 云原生中间件上云部署 Rocketmqkafkazookeeper
  • GPT的自回归语言建模(Autoregressive Language Modeling)
  • 科研小白成长记41——享受大起大落
  • 【排序用法】.NET开源 ORM 框架 SqlSugar 系列
  • 对拍详细使用方法
  • kubernetes——part3-2 集群声明式文件YAML
  • SQL优化与性能——数据库设计优化
  • Python中的六种“国际数字格式”实施方式
  • 刷LeetCode hot100--1.哈希表
  • Linux系统 异常控制流
  • 【CSS in Depth 2 精译_064】10.3 CSS 中的容器查询相对单位 + 10.4 CSS 容器样式查询 + 10.5 本章小结
  • 【连接池】.NET开源 ORM 框架 SqlSugar 系列
  • C_字符串其实就是字符数组
  • pcb线宽与电流