C语言之详细讲解文件操作(抓住文件操作的奥秘)

什么是文件

与普通文件载体不同,文件是以硬盘为载体存储在计算机上的信息集合,文件可以是文本文档、图片、程序等等。文件通常具有点+三个字母的文件扩展名,用于指示文件类型(例如,图片文件常常以KPEG格式保存并且文件扩展名为.jpg)。

将数据放入文件中,相比代码程序中堆栈上的数据,其优点在于可以随时做到需要时添加、舍弃时删除,数据可以持久化。

文件类型:

一般分为:程序文件与数据文件。

程序文件:

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

数据文件:

文件的内容不一定是程序,而是程序运行中的读取的数据。本章讨论的是数据文件。


文件的使用

在了解文件怎样使用前,我们先要了解流与标准流的概念

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

这样程序员在输入输出数据时不需要关心外部设备了,只需要将数据与流相连,C语言底层已经将流向不同外部设备的输入和输出实现好了,不需要我们关心。

我们只需要从流里读取数据,向流里写数据。

标准流


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

那是因为C语言程序在启动时已经将标准流(standard stream)准备好了。

默认打开了3个流:

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

stdout-标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到stdout-标准输出流(屏幕)中。
stderr-标准错误流,大多数环境中输出到显示器界面。

stdin、 stdout、 stderr 三个流的类型是: FILE*,通常称为文件指针。
C语言中,就是通过 FILE*的文件指针来维护流的各种操作的。

文件的操作

文件操作分为三步:打开文件(fopen)、读取或写入文件、关闭文件(fclose)。

文件指针

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系 统声明的,取名FILE.
FILE*pf;//文件指针变量pf

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

文件的打开与关闭

文件读写之前应该先打开文件,使用结束后应该关闭文件。
ANSIC 规定使用 fopen 函数来打开文件, fclose 函数来关闭文件。  

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

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

例:

#include<stdio.h>
#include<assert.h>int main() {FILE* pr = fopen("test.txt","w");//当没有文件时读取,fopen输出NULL//当没有文件写入时,会自动创建文件assert(pr);//这里使用assert断言,以防pr为空,也可以使用perror函数for (char ch = 'a'; ch <= 'z'; ch++) {fputc(ch, pr);//fputc函数将字符ch存入pr文件中}fclose(pr);return 0;
}

文件的使用方式:

按常用序:

文件的顺序读写:

1.写入一个字符

fgetc(字符c,文件指针);

2.读取一个字符

fputc(文件指针);
//每一次读取光标回向后移动一位
例:test.txt文件里面:abcdefg
char ch=fputc(pr);
printf(%c,ch);//输出为a;
char ch=fputc(pr);
printf(%c,ch);//输出为b;

3.写入一个字符串

fgets("hello,world",文件指针);
//每次的写入会导致数据的覆盖,在原先的数据后继续添加,需要使用a(追加);

4.读取指定长度的数据(读取数组)

char arr[10]={0};
fgets(arr,5,文件指针);//将所读取的数据存入arr数组中

5.读取结构体指定数据(fprintf);

#include<stdio.h>typedef struct S//typdef,以便更好的创建结构体变量
{char name[10];int age;}S1;int main()
{FILE* pf = fopen("test.txt", "w");if (pf != NULL)//也可用assert函数判断是否为空{S1 s1 = { "zhangsan", 18 };//创建变量s1fprintf(pf, "%s %d\n", s1.name, s1.age);fclose(pf);pf = NULL;}return 0;
}

文件的随机读写

fseek函数

fseek - C++ 参考 (cplusplus.com)

ftell - C++ Reference

ferror - C++ Reference

int fseek ( FILE * stream, long int offset, int origin );
                          流                  偏移量           起始位置
流:指向标识流的 FILE 对象的指针。
偏移量:二进制文件:要从源偏移的字节数。文本文件:零或 ftell 返回的值。

如果成功,该函数将返回零。
否则,它将返回非零值。
如果发生读取或写入错误,则设置错误指示符 (ferror)。

三种定位指针

#include<stdio.h>int main()
{FILE* pFile;pFile = fopen("test.txt", "r");//fputs("This is an apple.", pFile);fseek(pFile,2, SEEK_SET);//从起始位置的第二个偏移量int ch = fgetc(pFile);printf("%c", ch);fclose(pFile);return 0;
}

注意:

ftell函数

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

long int ftell ( FILE * stream );//注:返回为long int类型
#include <stdio.h>
int main()
{int n;FILE* pFile;char buffer[27];pFile = fopen("test.txt", "w+");for (n = 'A'; n <= 'Z'; n++)fputc(n, pFile);//向文本中输入字符rewind(pFile);//让文件指针回到起始位置fread(buffer, 1, 26, pFile);//读取1到26个数据fclose(pFile);buffer[26] = '\0';printf(buffer);//验证return 0;
}

feof函数(文件读取结束的判定)

feof - C++ 参考 (cplusplus.com)

文本文件:

  • fgetc 判断是否为 EOF .
  • fgets 判断返回值是否为 NULL
二进制文件:

        都是使用 fread() 读取,要判断其返回值与指定读取个数的大小,如果小于实际要读的个数,就说明发生读取异常,如果等于实际要读的个数,就说明是因读取成功而结束;

对于读取异常的判断,我们考虑判断 ferror() 函数的返回值:

若ferrror()为真——异常读取而结束;
若feof()为真——正常读取到尾而结束;

二进制文件和文本文件
我们知道数据在内存中是以二进制形式存储的,对于文件而言:如果不加转换直接输出到外存就是二进制文件;如果要在外存上以ASCII码形式存储,就需要提前转换最后以ASCII码值形式存储的文件就是文本文件。

对于字符,一律使用ASCII码形式存储,但对于数值型数据,即可以使用ASCII码存储也可以使用二进制形式存储。


oi!点个赞走吧!!!

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

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

相关文章

一文了解复杂度

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、算法效率二、时间复杂度1.定义2.大O的渐进表示法3.一般常见复杂度4.实例 三、空间复杂度1.定义2.空间复杂度计算3.实例 总结 前言 计算复杂性理论&#xf…

Redis的持久化方法,各自优缺点,怎么选择?

持久化&#xff1a; redis基于内存是数据库&#xff0c;内容存到内存中&#xff0c;也可以存到硬盘中&#xff0c;这个过程就叫持久化。有两种方案&#xff0c;RDB和AOP两种。 RDB RDB持久化就是把当前进程数据生成快照保存到硬盘的过程RDB文件是⼀个压缩的二进制文件&#…

VisualGLM-6B微调(V100)

Visualglm-6b-CSDN博客文章浏览阅读1.3k次。【官方教程】XrayGLM微调实践&#xff0c;&#xff08;加强后的GPT-3.5&#xff09;能力媲美4.0&#xff0c;无次数限制。_visualglm-6bhttps://blog.csdn.net/u012193416/article/details/131074962?ops_request_misc%257B%2522req…

【经典论文阅读1】FM模型——搜推算法里的瑞士军刀

全文由『说文科技』原创出品&#xff0c;文章同步更新于公众号『说文科技』。版权所有&#xff0c;翻版必究。 FM模型发表于2010年&#xff0c;它灵活好用且易部署。作者行文极其流畅&#xff0c;作者首先对要处理的问题进行介绍&#xff0c;接着作者提出FM模型&#xff0c;这…

Vue单页面应用和多页面应用的区别

概念&#xff1a; SPA单页面应用&#xff08;SinglePage Web Application&#xff09;&#xff0c;指只有一个主页面的应用&#xff0c;一开始只需要加载一次js、css等相关资源。所有内容都包含在主页面&#xff0c;对每一个功能模块组件化。单页应用跳转&#xff0c;就是切换…

笔试强训-day17_T2 十字爆破

一、题目链接 十字爆破 二、题目描述 牛牛在玩一个游戏&#xff1a; 一共有n行m列共nm个方格&#xff0c;每个方格中有一个整数。 牛牛选择一个方格&#xff0c;可以得到和这个方格同行、同列的所有数之和的得分。 例如&#xff1a;对于一个22的方格&#xff1a; 1 2 3 4 牛牛…

Python字符串常用方法(全网最细,仅此一份)

🥇作者简介:CSDN内容合伙人、新星计划第三季Python赛道Top1 🔥本文已收录于Python系列专栏: 👉Python从入门到精通 💬订阅专栏后可私信博主进入Python学习交流群,进群可领取Python180G全栈视频教程以及Python相关电子书合集 😊私信未回可以加V:hacker0327 备注P…

文心一言 VS 讯飞星火 VS chatgpt (251)-- 算法导论18.2 4题

四、假设关键字 {1&#xff0c;2&#xff0c;…&#xff0c;n} 被插入一棵最小度数为 2 的空 B 树中&#xff0c;那么最终的B树有多少个结点&#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; B树&#xff08;B-tree&#xff09;是一种自平衡的树&…

商务分析方法与工具(一):Python的趣味快捷-运算符、表达式与内置对象

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

组合数问题

1.直接用递推&#xff1a; 下面是AC代码“&#xff1a; #include<bits/stdc.h> using namespace std; const int N2010,mod1e97; int a[N][N]; void init() {for(int i0;i<N;i){for(int j0;j<i;j){if(j0) a[i][j]1;else a[i][j](a[i-1][j]a[i-1][j-1])%mod;}} } i…

结构体介绍(1)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 结构体&#xff08;1&#xff09; 前言一、struct介绍结构体声明结构体创建和初始化struct 的特殊声明结构体自引用 二、结构体内存对齐2.1.对齐规则 总结 前言 结构体 属于…

复习结构体

1.怎样使用结构体变量2.关于 . 和-> 的用法 pst -> age 会被计算机内部转化为&#xff08;*pst).age&#xff0c;这就是 ->的含义&#xff0c;是一种硬性规定 像 float 类型和 double 类型 &#xff0c;由于编码原因&#xff0c;一般都不能被精确存储 像 数字66.6在C…

【快速入门Linux】10_Linux命令—Vi编辑器

文章目录 一、vi 简介1.1 vi1.2 vim1.3查询软连接命令&#xff08;知道&#xff09; 二、打开和新建文件&#xff08;重点&#xff09;2.1 打开文件并且定位行2.2 异常处理 三、vi三种工作模式&#xff08;重点&#xff09;3.1 末行模式-命令 四、常用命令4.0 命令线路图4.1 移…

多态及相关

多态及相关 多态的概念多态实现的两个条件及特殊情况虚函数虚函数重写的例外C11 override 和 final 重载、覆盖(重写)、隐藏(重定义)的对比题目1抽象类接口继承和实现继承 题目2&#xff08;很重要&#xff09;多态的原理虚函数表为什么Derive中的func4()在监视窗口里没有显示出…

利用大模型提升个性化推荐的异构知识融合方法

在推荐系统中&#xff0c;分析和挖掘用户行为是至关重要的&#xff0c;尤其是在美团外卖这样的平台上&#xff0c;用户行为表现出多样性&#xff0c;包括不同的行为主体&#xff08;如商家和产品&#xff09;、内容&#xff08;如曝光、点击和订单&#xff09;和场景&#xff0…

Javascript基础(三)

Javascript基础&#xff08;一&#xff09; Javascript基础&#xff08;二&#xff09; 引用数据类型 在之前的文章中&#xff0c;我们提及了与基本数据类型并列的引用数据类型&#xff0c;当时提到引用数据类型大致分为三类&#xff1a;数组Array&#xff0c;函数Function&a…

GPT-ArcGIS数据处理、空间分析、可视化及多案例综合应用

在数字化和智能化的浪潮中&#xff0c;GIS&#xff08;地理信息系统&#xff09;和GPT&#xff08;生成式预训练模型&#xff09;的结合正日益成为推动科研、城市规划、环境监测等领域发展的关键技术。GIS以其强大的空间数据处理、先进的空间分析工具、灵活的地图制作与可视化能…

JavaEE初阶-多线程易忘点总结

文章目录 1.PCBPID文件描述符表内存指针状态上下文优先级记账信息tgid 2.线程与进程的区别3.sleep和interrupt方法的关系变量终止线程interrupt方法终止线程 4.线程状态5.出现线程不安全的原因线程在系统中是随即调度&#xff0c;抢占式执行的。多个线程修改同一个变量线程针对…

《MySQL对数据库中表的结构的操作》

文章目录 一、建表二、查看表结构所有能查看到数据库&#xff0c;表的操作痕迹的本质都是服务器保存下来了这些操作记录。 三、修改表1.改表名字2.添加表记录3.添加表的更多字段4.修改表的字段5. 删除表的字段 总结 以下的数据库表的操作全是基于user_db这个数据库操作的&#…

如何加入亚马逊云科技AWS特邀技领云合作博主

这一年来&#xff0c;小李哥帮助过上千名小伙伴学习AWS和考取认证&#xff0c;这次非常荣幸能和丸子爸比大哥、程序员学习日常成为第一批亚马逊AWS云领袖计划的特邀合作博主&#xff01;感谢AWS培训与认证各位老师的支持&#xff0c;未来小李哥会继续坚持社区分享&#xff0c;带…