C语言:文件操作详解

什么是文件

        文件是是计算机硬盘存储的数据的集合,它可以是文本文档,也可以是图片,程序等等。将数据存储进文件内可以很好的保存数据,方便程序员对文件的操作。

文件的类型

        一般根据存储数据类型的不同可以分为二进制文件文本文件。数据在内存中是以二进制存储的,不加任何转换的输出就是二进制文件,如果要求数据在外存以ASCII码(美国信息交换标准代码)的形式显示就是文本文件。

需要注意的是,数值型数据在外存中既可以以二进制存储,也可以以ASCII值存储,字符型数据在外存中只能以ASCII值存储,而这两者在内存中都是以二进制存储的。

文件操作

流的概念

        我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出 操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流 想象成流淌着字符的河。 C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。 ⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。 

换句话说:流就是程序员与外部沟通的桥梁

        同样在对文件进行操作的时候本质上也是数据的输入与输出,所以也要以流为介质,每个文件都有一个与之对应的文件信息区(也就是所谓的流),我们可以通过定义FILE*(文件指针)类型的变量实现与文件有关的操作。

标准流

C语言程序在启动时默认打开了三个流:

  • stdin —— 标准输入流,用于获取从键盘上输入的数据,如scanf,fscanf(后续会讲)等
  • stdout —— 标准输出流,将从键盘获取的数据显示在控制台(就是屏幕)上,如printf,fprintf等
  • stderr —— 标准错误流,将错误信息显示在控制台上

        标准流可以理解为数据读取和输出都是在屏幕上进行的,而在文件操作时会用到文件流,也就是专门进行文件操作的流,通过文件流就可以使用各种函数较好的对文件进行维护。

文件操作的步骤

        那么我们该如何找到文件呢?

FILE* pf=NULL;

        C语言规定,所有的文件操作都是基于文件类型的指针,也就是说,通过⽂件指针变量能够间接找到与它关联的⽂件

文件操作大概可以分为三步:

  1. 打开文件(fopen)
  2. 读/写文件
  3. 关闭文件(fclose)

代码框架如下:

        VS编译环境下需要在头文件前加#define  _CRT_SECURE_NO_WARNINGS预编译指令,因为编译器认为fopen是不安全的。

        几乎所有的文件操作的都是基于这个模板开展的。

int main()
{//创建文件指针并打开文件FILE* pf = fopen("test_3_26", "r");//判断是否能打开文件if (pf == NULL){perror("fopen");//显示报错信息return 1;}//文件操作(读/写)/*.......*///关闭文件fclose(pf);pf = NULL;//将pf置空防止其成为野指针return 0;
}

接下来我们会对在文件操作中常用的函数进行讲解。

文件的打开与关闭 

fopen

作用:打开指定路径下的文件。

FILE * fopen ( const char * filename, const char * mode );

参数1

const char * filename:打开文件的路径,可分为绝对路径相对路径:

  • 绝对路径是文件或目录在文件系统中的完整路径,从根目录开始一直到目标文件或目录的路径描述。
    使用绝对路径时,需要提供完整的路径信息,包括根目录。
    例如,Windows 系统中的绝对路径可能类似于 C:\Users\Username\Documents\photos,Linux 或 macOS 中的绝对路径可能类似于 /home/username/documents/photos

  • 相对路径是相对于当前工作目录(当前所在位置)的路径。
    使用相对路径时,文件或目录的位置是相对于当前位置的描述,不需要从根目录开始描述。
    例如,在一个名为 documents 的文件夹中有一个子文件夹 photos,要访问 photos 文件夹可以使用相对路径 ./photos。在C程序中如果文件和main文件在同一个文件夹下,相对路径就是文件名+后缀名

参数2

const char * mode:打开文件的方式(只需要记最常用的几种即可)

⽂件使⽤⽅式含义如果指定⽂件不存在
“r”(只读)为了输⼊数据,打开⼀个已经存在的⽂本⽂件出错
“w”(只写)为了输出数据,打开⼀个⽂本⽂件建⽴⼀个新的⽂件
“a”(追加)向⽂本⽂件尾添加数据建⽴⼀个新的⽂件
“rb”(只读)为了输⼊数据,打开⼀个⼆进制⽂件出错
“wb”(只写)为了输出数据,打开⼀个⼆进制⽂件建⽴⼀个新的⽂件
“ab”(追加)向⼀个⼆进制⽂件尾添加数据建⽴⼀个新的⽂件
“r+”(读写)为了读和写,打开⼀个⽂本⽂件出错
“w+”(读写)为了读和写,建议⼀个新的⽂件建⽴⼀个新的⽂件
“a+”(读写)打开⼀个⽂件,在⽂件尾进⾏读写建⽴⼀个新的⽂件
“rb+”(读写)为了读和写打开⼀个⼆进制⽂件出错
“wb+”(读 写)为了读和写,新建⼀个新的⼆进制⽂件

建⽴⼀个新的⽂件

返回值:如果打开文件成功返回该文件的地址,打开失败返回NULL。

样例:

/*文件操作模板省略*/FILE* pf = fopen("test_3_26", "r");//以“只读”的方式打开文件
if (pf == NULL)
{fclose(pf);//关闭文件perror("fopen");return 1;
}

fclose  

作用关闭参数指针指向的文件

int fclose ( FILE * stream );

参数FILE*stream:直接传入指向要关闭文件的指针即可(如上文中的pf)。

返回值:如果文件被成功关闭则返回返回0,如果失败返回非0值 。

 文件的顺序读写

函数名功能适⽤于
fgetc字符输⼊函数所有输⼊流
fputc字符输出函数所有输出流
fgets⽂本⾏输⼊函数所有输⼊流
fputs⽂本⾏输出函数所有输出流
fscanf格式化输⼊函数所有输⼊流
fprintf格式化输出函数所有输出流
fread⼆进制输⼊⽂件
fwrite⼆进制输出⽂件

        对于本文来说,适用于所有流的意思是该函数既可以在标准流中进行输入或输出,也可以在文件中输入或输出,只适用于文件流代表该函数只能在文件中进行数据操作。

fgetc

作用:从文件流中获取一个字符(一次只能获取一个字符),需要注意的是每次调用fgetc函数后文件中的光标会后移读取下一个字符,直到EOF。

int fgetc ( FILE * stream );

参数:指向指定文件的指针。

返回值:如果成功读取到字符,则返回该字符的ASCII码值;如果读取失败或文件结束(EOF)返回EOF。

样例:

//读取文本文件text_3_26中的所有字符
/*文件操作模板省略*/int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{printf("%c\n", ch);
}

输出结果:

fputc

作用:每次向文件中写入一个字符,写入成功后光标后移。

int fputc ( int character, FILE * stream );

参数:

  1. int character:要写入文件的字符
  2. FILE * stream:指向要写入文件的指针

返回值:如果字符被成功写入返回被写入字符的ASCII值,如果写入失败返回EOF。

样例:

/*文件操作模板省略*/fputc('a', pf);
fputc('b', pf);
fputc('c', pf);
fputc('d', pf);
fputc('e', pf);

输出结果:

fputs

作用:向文件中写入字符串

int fputs ( const char * str, FILE * stream );

参数:

  1. const char * str:被写入的字符串。
  2. FILE * stream:指向文件的指针。

返回值:成功写入返回一个非负值,写入失败返回EOF。

样例:

        在多次调用fputs函数时如果不加'\n'修饰,字符串会在上次光标停留处继续打印在同一行,在字符串后加上'\n'才会换行输出。

  • 不加'\n'
fputs("hello world", pf);
fputs("hello world", pf);

运行结果:

  • 加'\n'
fputs("hello world\n", pf);
fputs("hello world", pf);

运行结果:

fgets

作用:从文件中最多读取num-1个字符并存入字符串,并在字符串结尾加上'\0'(第num个字符)

char * fgets ( char * str, int num, FILE * stream );

参数:

  1. char * str:指向从文件中读取的字符串的字符指针。
  2. int num:最多从文件中读取的num-1个字符,第num位放'\0'。

返回值:成功后,该函数返回 str。如果在尝试读取字符时遇到文件末尾,返回NULL。如果在读取任何字符之前发生这种情况,则返回的指针为空指针NULL(并且 str 的内容保持不变)。如果发生读取错误,则报错,并返回空指针NULL(但 str 指向的内容可能已更改)。

样例:

char arr[10] = { 0 };
fgets(arr, 10, pf);

     

   

        fgets只能读取在同一行的字符,而且如果条件允许'\n'也会读取进来,但是不会换行的读取。

读取文件中的全部数据:

/*文件操作模板省略*/char arr[20] = { 0 };
while (fgets(arr, 20, pf) != NULL)//读取到文件末尾返回NULL
{printf("%s", arr);
}

运行结果:

        

 fscanf

作用:从文件中读取格式化的数据。

int fscanf ( FILE * stream, const char * format, ... );

参数:

  1. FILE * stream:打开文件的指针。
  2. 参数数量不固定,根据变量类型和数量而定

返回值:成功后,该函数返回成功填充的参数列表的项数。也可能由于匹配失败、读取错误或文件末尾的范围而更少(甚至为零)。如果在读取时发生读取错误或到达文件末尾,报错。而且,如果在成功读取任何数据之前发生任何情况,则返回 EOF。

样例:

struct Student
{int age;char name[20];float score;
};/*文件操作模板省略*/struct Student s = { 0 };
fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));//从文件中获取数据printf("%s %d %.1f", s.name, s.age, s.score);

运行结果:

fprintf

作用:向文件中写入格式化数据(以文本的形式)

int fprintf ( FILE * stream, const char * format, ... );

参数:

  1. FILE * stream:指定的文件指针
  2. const char * format, ...对应向文件中输出的数据的类型

返回值:成功后,将返回写入的字符总数。如果发生写入错误,则返回负数。

样例:

struct Student
{char name[20];int age;float score;
};/*文件操作模板省略*/
//FILE* pf = fopen("test_3_26.txt", "w+");//打开方式修改为"w+"struct Student s = {"张三",18,65.5};
fprintf(pf, "%s %d %f", s.name, s.age, s.score);

运行结果:

fwrite

作用:以二进制的的形式向文件中写入

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

参数:

  1. const void * ptr:指向被写入元素内存块的指针。
  2. size_t size:被写入元素的数据类型。
  3. size_t count:写入元素的个数。
  4. FILE * stream:文件指针。

返回值:返回成功写入的元素总数。如果此数字与 count 参数不同,则写入错误会阻止函数完成。如果 size 或 count 为零,则函数返回零。

样例:

/*文件操作模板省略*/
//FILE* pf = fopen("test_3_26.txt", "rb");//以"rb"打开文件int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 0 };
fwrite(arr1, sizeof(arr1[0]), 5, pf);//以二进制形式写入

运行结果:

        以二进制形式输入的数据我们是看不懂的,需要搭配fread函数(见后文)读出来。

fread

作用:以二进制的形式从文件中读取数据(只适用于文件流)。

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

参数:

  1. void * ptr:从文件中读取的数据放在ptr中。
  2. size_t size:读取数据类型的大小。
  3. size_t count:读取元素的个数。
  4. FILE * stream:文件指针。

返回值:返回成功读取的元素总数。如果此数字与 count 参数不同,则表示读取时发生读取错误或到达文件末尾。如果 size 或 count 为零,则该函数返回零。

样例:

/*文件操作模板省略*/
//FILE* pf = fopen("test_3_26.txt", "rb");//以"rb"打开文件int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 0 };
fread(arr2, sizeof(arr2[0]), 5, pf);//以二进制形式读取
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:

文件的随机读写

fseek

作用: 根据⽂件指针的位置和偏移量来定位⽂件指针。

int fseek ( FILE * stream, long int offset, int origin );

参数:

  1. FILE * stream:文件指针。
  2. long int offset:相对于起始位置的偏移量。
  3. int origin:起始位置。
  • 第三个参数起始位置一共有三种类型
  • 参数文件指针的起始位置
    SEEK_SET文件开头
    SEEK_CUR文件指针的当前位置
    SEEK_END

    文件末尾

返回值:如果成功,该函数将返回零。否则返回非零值。

样例:

        当参数origin位SEEK_END时,此时的偏移量应为负值。

  • 偏移量位正或0
/*文件操作模板省略*/
//FILE* pf = fopen("test_3_26.txt", "r");//以"r"打开文件int ch1 = fgetc(pf);//a
int ch2 = fgetc(pf);//b
int ch3 = fgetc(pf);//c
printf("%c %c %c\n", ch1, ch2, ch3);fseek(pf, 0, SEEK_SET);//相对于文件开头偏移0个单位int ch4 = fgetc(pf);//a
printf("%c\n", ch4);

运行结果:

  • 偏移量为负
/*文件操作模板省略*/int ch1 = fgetc(pf);//a
int ch2 = fgetc(pf);//b
int ch3 = fgetc(pf);//c
printf("%c %c %c\n", ch1, ch2, ch3);fseek(pf, -1, SEEK_END);//相对于文件末尾偏移1个单位int ch4 = fgetc(pf);//g
printf("%c\n", ch4);

运行结果:

ftell

作用: 返回⽂件指针相对于文件开头的偏移量。(fseek函数可以规定字符指针的位置,见前文)

long int ftell ( FILE * stream );

参数:FILE * stream:文件指针。

返回值:文件指针相对于文件开头的偏移量。

样例:

        当文件指针位于文件末尾时,ftell的返回值就是该文件中所有的字符数。

/*文件操作模板省略*/
fseek(pf, 0, SEEK_END);//文件末尾
printf("%d\n", ftell(pf));

运行结果:

rewind

作用:将文件指针的位置设置为开头。

void rewind ( FILE * stream );

参数:FILE * stream:文件指针。

样例:

/*文件操作模板省略*/
int ch1 = fgetc(pf);//a
int ch2 = fgetc(pf);//b
int ch3 = fgetc(pf);//c
printf("%c %c %c\n", ch1, ch2, ch3);rewind(pf);int ch4 = fgetc(pf);//a
printf("%c\n", ch4);

运行结果:

文件读取结束的判定

feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束。
1. ⽂本⽂件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。
例如:
fread判断返回值是否⼩于实际要读的个数。

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

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

相关文章

服务器监控软件夜莺采集监控(三)

文章目录 一、采集器插件1. exec插件2. rabbitmq插件3. elasticsearch插件 二、监控仪表盘1. 系统信息2. 数据服务3. NginxMQ4. Docker5. 业务日志 一、采集器插件 1. exec插件 input.exec/exec.toml [[instances]] commands ["/home/monitor/categraf/scripts/*.sh&q…

AI智能分析网关V4数字农场智能监控方案

随着大数据时代的到来&#xff0c;数据成为国家基础性战略资源&#xff0c;加快数字化转型、以数字化谋求国际竞争新优势已成为全球普遍共识&#xff0c;利用大数据推动经济发展、优化社会治理、改善公共服务成为了世界各国的必然选择。农村为实现产业转型升级和治理创新&#…

HBase的Python API操作(happybase)

一、Windows下安装Python库&#xff1a;happyhbase pip install happybase -i https://pypi.tuna.tsinghua.edu.cn/simple 二、 开启HBase的Thrift服务 想要使用Python API连接HBase&#xff0c;需要开启HBase的Thrift服务。所以&#xff0c;在Linux服务器上&#xff0c;执行…

算法之美:二叉树演进之多叉树及B-Tree树原理

在上篇文章我们了解了平衡二叉树的优势&#xff0c;了解到平衡二叉树能够对不平衡的节点施加旋转&#xff0c;使得树达趋于平衡&#xff0c;以提升查询效率&#xff0c;操作效率很高&#xff0c;与之同时也存在着不少的问题&#xff0c;例如我们在实际使用中会通常会将树加载到…

【Flink架构】关于FLink BLOB的组织架构:FLIP-19: Improved BLOB storage architecture:官网解读

文章目录 一. BlobServer架构1.BlobClient2. BlobServer3. BlobCache4. LibraryCacheManager 二、BLOB的生命周期1. 分阶段清理2. BlobCache的生命周期3. BlobServer 三、文件上下载流程1. BlobCache 下载2. BlobServer 上传3. BlobServer 下载 四. Flink中支持的BLOB文件类型1…

SPI机制详解

在上一篇 gRPC源码剖析-Server启动流程 有提到过SPI机制&#xff0c;SPI对于大多数业务开发人员可能并不熟悉&#xff0c;但是在各底层基础框架中用得还是比较多的&#xff0c;今天我们来详细了解一下。 一、SPI机制 SPI&#xff0c;全称是Service Provider Interface,就是为…

微软正在改进其AI驱动的Copilot在Microsoft Teams中的工作方式,为会议聊天、总结等引入了新的召唤助手方式

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【spring】@Value注解学习

Value介绍 Value 是 Spring 框架中一个非常有用的注解&#xff0c;它允许你将来自配置文件、系统属性、环境变量或者通过 SpEL&#xff08;Spring Expression Language&#xff09;表达式计算得出的值注入到 Spring 管理的 Bean 中。这个注解可以用在字段、setter 方法或者构造…

自动化面试常见算法题!

1、实现一个数字的反转&#xff0c;比如输入12345&#xff0c;输出54321 num 12345 num_str str(num) reversed_num_str num_str[::-1] reversed_num int(reversed_num_str) print(reversed_num) # 输出 54321代码解析&#xff1a;首先将输入的数字转换为字符串&#xff…

【研发日记】Matlab/Simulink开箱报告(十)——Signal Routing模块模块

文章目录 前言 Signal Routing模块 虚拟模块和虚拟信号 Mux和Demux Vector Concatenate和Selector Bus Creator和Bus Selector 分析和应用 总结 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;五&#xff09;——S-Fuction模块(C MEX S-Fun…

python学习15:python中的input语句

python中的input语句 我们前面学习过print语句&#xff0c;可以将内容输出到屏幕上&#xff1b;在python中&#xff0c;与之对应的还有一个input语句&#xff0c;用来获取键盘输入。 数据输出&#xff1a;print 数据输入&#xff1a;input 使用上也很简单&#xff1a; 使用inp…

LIS、LCS算法模型

文章目录 1.LCS算法模型2.LIS算法模型 1.LCS算法模型 LCS问题就是给定两个序列A和B&#xff0c;求他们最长的公共子序列。 在求解时&#xff0c;我们会设dp[i][j]表示为A[1 ~ i]序列和B[1 ~ j]序列中&#xff08;不规定结尾&#xff09;的最长子序列的长度。 if(a[i]b[i]) dp…

信号处理--情绪分类数据集DEAP预处理(python版)

关于 DEAP数据集是一个常用的情绪分类公共数据&#xff0c;在日常研究中经常被使用到。如何合理地预处理DEAP数据集&#xff0c;对于后端任务的成功与否&#xff0c;非常重要。本文主要介绍DEAP数据集的预处理流程。 工具 图片来源&#xff1a;DEAP: A Dataset for Emotion A…

从零开始为香橙派orangepi zero 3移植主线linux——1.uboot

从零开始为香橙派orangepi zero 3移植主线linux——1.uboot 0.前言一、准备二、制作引导文件1.BL312.SCP firmware (Crust)3.uboot 三、烧录四、运行 0.前言 之前买了块香橙派zero3&#xff0c;CPU是全志H618&#xff0c;四核cortex-A53&#xff0c;烧录了官方的ubuntu系统后就…

《论文阅读》PAGE:一个用于会话情绪原因蕴含基于位置感知的图模型 ICASSP 2023

《论文阅读》PAGE&#xff1a;一个用于会话情绪原因蕴含基于位置感知的图模型 ICASSP 2023 前言 简介任务定义模型构架Utterances Encoding with EmotionPosition-aware GraphCausal Classifier实验结果 前言 亲身阅读感受分享&#xff0c;细节画图解释&#xff0c;再也不用担…

2024年腾讯云4核8G服务器多少钱一年?买1年送3个月

2024年腾讯云4核8G服务器租用优惠价格&#xff1a;轻量应用服务器4核8G12M带宽646元15个月&#xff0c;CVM云服务器S5实例优惠价格1437.24元买一年送3个月&#xff0c;腾讯云4核8G服务器活动页面 txybk.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器优惠价格 轻…

【深度学习】【机器学习】用神经网络进行入侵检测,NSL-KDD数据集,基于机器学习(深度学习)判断网络入侵

文章目录 下载数据集NSL-KDD数据集介绍输入的41个特征输出的含义数据处理&&训练技巧建神经网络&#xff0c;输入41个特征&#xff0c;输出是那种类别的攻击模型训练模型推理写gradio前端界面&#xff0c;用户自己输入41个特征&#xff0c;后端用模型推理计算后显示出是…

微服务(基础篇-006-Docker)

Docker是一个开源的应用容器引擎&#xff0c;它让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何Linux机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间没有任何接口&#xff08;类似 iPhone 的 app&…

【OpenCV】 OpenCV (C++) 与 OpenCvSharp (C#) 之间数据通信

OpenCV是一个基于Apache2.0许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等语…

阿里云实时计算Flink的产品化思考与实践【上】

摘要&#xff1a;本文整理自阿里云高级产品专家黄鹏程和阿里云技术专家陈婧敏在 FFA 2023 平台建设专场中的分享。内容主要为以下五部分&#xff1a; 阿里云实时计算 Flink 简介产品化思考产品化实践SQL 产品化思考及实践展望 该主题由黄鹏程和陈婧敏共同完成&#xff0c;前半程…