C语言文件操作详解

1. 什么是文件:

     文件是计算机中存储数据的一种方式,它可以包含文本、图像、音频、视频等各种形式的信息。在计算机系统中,文件被组织成一个个独立的单元,可以通过文件名来标识和访问。文件可以存储在计算机的硬盘、固态硬盘、光盘、U盘等存储介质上,文件通常由两部分组成:文件名和文件内容。文件名是用来标识文件的唯一名称,可以根据需要进行命名。文件内容是实际存储在文件中的数据,可以是文本、二进制数据或其他格式的数据,文件在计算机系统中起到了重要的作用,它们可以用于存储和传输数据,作为程序的输入和输出,以及用于组织和管理数据。通过文件系统,用户可以创建、打开、读取、写入、修改和删除文件。

1.1. windows中文件的类型:

        前边我们聊到不同后缀代表着不同的文件类型,下边我们来了解一下常见的文件类型:

  1. text.txt 后缀为.txt的为文本文件
  2. text.exe 后缀为.exe的为可执行文件
  3. text.jpg 后缀为.jpg的为图片文件
  4. text.mp3 后缀为.mp3的为音频文件
  5. text.mp4 后缀为.mp4的为视频文件

上图中仅为部分文件类型,如有兴趣的小伙伴可以去深入了解喔

1.2. c程序中的文件:

        一个c程序要想变成最终可以执行的文件,会经历编译-->链接-->运行三个步骤,而这三个步骤又分别对应着三个不同的文件.c文件编译以后先生成.o(.obj)文件,链接生成.exe的可执行文件,最终再执行

1.3. 二进制文件及文本文件:

二进制文件:数据在内存当中是以二进制的格式存储的,如果不加以转换直接输出到外存文件当中的称为二进制文件

文本文件:存入文件前加以转换为1ASCII格式存储在文件中的文件为文本文件

举例:假设有一个数字5000,那么它以二进制或文本的形式在内存当中分别是如何存储的呢

(注:相应的ASCII码值对应着不同的十进制数,字符5的ASCII码值为00110101 0为00110000)

2. 文件流:

        文件流是一种用于读取和写入文件的数据流。它提供了一种方便的方式来处理文件的输入和输出操作,我们常使用的printf函数和scanf函数所对应使用的就是标准输入和输出流,只不过这些流在我们打开编译器时已经默认开启了,所以对应程序员来说直接使用即可

c程序默认打开的流:

        stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据
         stdout - 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出 流中
        stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯

C语言提供了标准库函数来支持文件流操作,主要包括以下几个步骤:

  1. 打开文件:使用fopen函数打开一个文件,并返回一个指向该文件的指针。需要指定文件名和打开模式(如读取、写入、追加等)

  2. 读取文件:使用fscanffgets等函数从文件中读取数据。fscanf可以按照指定的格式从文件中读取数据,而fgets则逐行读取字符串

  3. 写入文件:使用fprintffputs等函数将数据写入文件。fprintf可以按照指定的格式将数据写入文件,而fputs则将字符串写入文件

  4. 关闭文件:使用fclose函数关闭已打开的文件。关闭文件后,将释放相关的资源

C语言文件流的使用需要注意以下几点:

  • 在打开文件时,需要确保文件存在或者具有相应的权限
  • 在读取或写入文件时,需要确保文件指针指向正确的位置
  • 操作完成后,需要及时关闭文件,以释放资源

3. 文件指针的创建:

        文件指针的创建与前文中的指针创建大同小异,FILE* 变量名

int main()
{FILE* pf;   //文件的创建return 0;
}
定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个⽂件的⽂件信息区(是⼀个结构体变 量)通过该⽂件信息区中的信息就能够访问该⽂件,也就是说,通过⽂件指针变量能够间接找到与 它关联的⽂件

举例:

4. 文件的打开与关闭:

4.1. fopen与fclose函数:

fopen函数:打开文件

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

filename:要打开的文件

mode:以什么样的方式打开文件

(如果文件被成功打开,返回一个指向file对象的指针,否则返回NULL)

fclose函数:关闭文件

int fclose ( FILE * stream );

stream:指向file文件的指针,该对象为要关闭的流

(如果文件被成功关闭,返回0,关闭失败,返回EOF)

file打开时mode参数:

举例:

int main()
{FILE* pf;   //文件的创建pf = fopen("a1.txt", "wb");if (pf != NULL)  //判断文件是否打开成功{int i = 0;while (i < 11){fputc(i, pf); //fputc写入一个字符i++;}fclose(pf);  //关闭文件}return 0;
}

5. 文件的顺序读写:

5.1. 顺序读写函数:

5.2. fgets函数:

从文件中获取一个字符

int fgetc ( FILE * stream );

(如果读取成功,返回读取的字符,整形提升至int型,读取失败返回EOF)

举例:

int main()
{FILE* p;p = fopen("test1.txt", "r");if (p != NULL){int a = fgetc(p);printf("%d", a);fclose(p);}return 0;
}//执行结果
97 所以该字符是a,a的ASCII值为97

5.3. fputc函数:

写入一个字符到文件中:

int fputc ( int character, FILE * stream );

character:写入的字符

(如果写入成功,则字符被写入到文件当中,失败返回EOF)

举例:

int main()
{FILE* p1;p1 = fopen("test1.txt", "w");if (p1 != NULL){fputs("a", p1);fclose(p1);}return 0;
}//执行结果
此时test1.txt文件当中写入了字符a

5.4. fgets函数:

从文件当中获取字符串

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

(如果读取成功,返回str,如果读取到文件末尾,则设置eof指示符(feof),读取失败返回NULL)

举例:

int main()
{FILE* p2;char a[100];p2 = fopen("test1.txt", "r");if (p2 != NULL){if (fgets(a, 20, p2) != NULL){printf("%s", a);}fclose(p2);}return 0;
}

5.5. fputs函数:

将字符串写入到文件中

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

(如果成功返回一个>0的数,失败函数返回EOF并设置错误指示器)

举例:

int main()
{FILE* p3;char a[] = "qwerty";p3 = fopen("test1.txt", "w");if (p3 != NULL){int a1 = fputs(a, p3);if (a1 >= 0)fclose(p3);elseperror("fputs:");}return 0;
}

5.6. fscanf函数和fprintf函数:

5.6.1. scanf函数以及printf函数:

在讲fscanf以及fprintf这两个函数前,我们先来了解一下scanf和printf函数又是如何使用的呢

语法:

int printf ( const char * format, ... );  //格式化输入函数
int scanf ( const char * format, ... );   //格式化输出函数

下边我们来看看它们是如何使用的:

//从键盘上输入一个数,输出到控制台中
int main()
{int a = 0;scanf("%d", &a);printf("a的值为:%d", a);return 0;
}

该两个函数为格式化输入输出函数,所以在使用这两个函数时必须带有格式,那么它们又和fscanf和fprintf有什么区别呢,下边我们一起来了解一下

5.6.2. fscanf,fprintf,scanf及printf四个函数的区别:

语法:
int fscanf ( FILE * stream, const char * format, ... );
int fprintf ( FILE * stream, const char * format, ... );

(如果成功,返回函数成功填充的项数,而匹配失败或者到达文件末尾返回值小于或等于0,在任何数据都未被读取到之前发生错误,fnahuiEOF)

差异对比:

fscanf的使用:
int main()
{FILE* p4;p4 = fopen("test1.txt", "r+"); //以读的方式打开int s = 1000;char a2[10] = { 0 };if (p4 != NULL){int a3 = fscanf(p4, "%d%s", &s,a2); //读取两个数放入相对应的变量当中if (a3 != EOF){printf("%d\n", s);printf("%s\n", a2);fclose(p4);}else{perror("fscanf");}}return 0;
}
fprintf的使用:
int main()
{FILE* p4;p4 = fopen("test1.txt", "w+");int s = 1000;char a2[10] = "abcdef";if (p4 != NULL){int a3 = fprintf(p4, "%d%s", s, a2);if (a3 != EOF){fclose(p4);}else{perror("fprintf");}}return 0;
}

如何使用fscanf或fprintf将数据输入输出到控制台当中:

(这里就要使用到我们之前所讲的输入输出流了)

举例:

int main()
{int a = 0;printf("请输入一个数:");int q = fscanf(stdin, "%d", &a); //stdin标准输入流if (q == EOF){perror("fscanf");}fprintf(stdout, "a此时的值为:%d", a); //stdout标准输出流return 0;
}//执行结果
请输入一个数:123
a此时的值为:123

同理前边适用于所以流的函数都可以如此使用

5.7. fread函数:

以二进制的方式在文件中读取数据

语法:

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

(如果读取成功,返回读取的个数,如果size和count为0,则函数返回0,函数内容不发生改变)

ptr:指向大小至少为(size_t count)字节的内存块的指针,转换为void*类型

size:要读取的每个元素大小,单位是字节

count:读取的个数

stream:文件指针

举例:

#include <stdlib.h>
int main()
{FILE* p5;int count = 5;char* pf = (char*)malloc(sizeof(char) * count);if (pf == NULL){perror("malloc");return 1;}p5 = fopen("test1.txt", "rb"); //以二进制的方式读取数据if (p5 != NULL){int q = fread(pf, sizeof(char), count, p5);for (int i = 0; i < count; i++){printf("%c ", *(pf + i));}fclose(p5);}else{perror("fopen");}free(pf);pf = NULL;
}//执行结果
a b c d e

如有对动态内存malloc这些不理解的小伙伴可以去看看动态内存管理这篇文章哟

5.8. fwrite函数:

语法:

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

(与fread函数大同小异,这里博主就不做结束咯)

举例:

#include <stdlib.h>
int main()
{FILE* p6;int count = 5;char a5[] = "sdfgh";p6 = fopen("test1.txt", "wb"); //以二进制的方式读取数据if (p6 != NULL){int q = fwrite(a5, sizeof(char), count, p6);fclose(p6);}else{perror("fopen");}
}//执行结果
此时成功向test1.txt文件当中添加数组a5中的字符串

6. 文件的随机读取:

6.1 fseek函数:

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

stream:文件指针

offset:二进制文件:要从原点偏移的字节数

             文本文件:要么为0,要么有ftell返回一个值

origin:表示偏移量的开始位置

                SEEK_SET:文件的起始位置

                SEEK_CUR:文件指针当前结束的位置

                SEEK_END:文件的结束位置

(如果成功返回0,否则,返回非零值)

举例:

int main()
{FILE* pFile;pFile = fopen("test1.txt", "wb");fputs("I'm is a handsome guy", pFile); //向文件中写入一组字符fseek(pFile, 7, SEEK_SET);  //光标从5的位置开始执行操作fputs("no ", pFile);  fclose(pFile);return 0;
}//执行结果
I'm is no andsome guy

6.2 ftell函数:

语法:

long int ftell ( FILE * stream );

(如果成功,返回位置指示器当前的值,失败,返回-IL)

举例:

(相较于之前的代码,咱来举例看看)

int main()
{FILE* pFile;pFile = fopen("test1.txt", "wb");fputs("I'm is a handsome guy", pFile); //向文件中写入一组字符fseek(pFile, 7, SEEK_SET);  //光标从5的位置开始执行操作fputs("no ", pFile);long size = ftell(pFile);  //判断文件中光标的位置printf("%ld", size);fclose(pFile);return 0;
}

6.3 rewind函数:

语法:

void rewind ( FILE * stream );

(让文件指针的位置回到起始位置)

举例:

int main()
{FILE* p7;p7 = fopen("test1.txt", "w");if (p7 != NULL){int q = fputs("abcdefgh", p7); //向文件当中写入“abcdefg”这个字符串if (q == EOF){perror("fputs");}fseek(p7, 4, SEEK_SET);  //此时文件指针应指向erewind(p7);  //将文件指针返回到文件起始位置FILE* p8 = fopen("test1.txt", "r");char q1 = fgetc(p8);  //此时q1的值应为aprintf("%c\n", q1);fclose(p7);fclose(p8);}else{perror("fopen");}return 0;
}//执行结果
a

7. 文件读取结束的判定:

7.1 错误使用的feof函数:

语法:

int feof ( FILE * stream );

(如果设置l与流相关的文件结束指示符,则返回一个非零值,否则返回零)

牢记:在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束
feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束
  1. ⽂本⽂件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
  2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数
举例:
int main()
{FILE* p9;int q = 0;  //记录文件读取的个数p9 = fopen("test1.txt", "r");if (p9 != NULL){while (fgetc(p9) != EOF){q++;}if (ferror(p9))   //文件错误时返回0printf("文件读取发生错误!\n");else if (feof(p9))printf("文件读取完毕\n");fclose(p9);}else{perror("fopen");}printf("文件中有多少个字符:%d", q);return 0;
}//执行结果
文件读取完毕
文件中有多少个字符:8   

8. ⽂件缓冲区:

        ANSIC 标准采⽤“缓冲⽂件系统” 处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为 程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输 ⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等),缓 冲区的⼤⼩根据C编译系统决定的

下边小博给兄弟们找个一个题解方便大家进一步了解:

(今日分享到此结束,如觉得有帮助还请点赞三联支持一波呢,Thanks♪(・ω・)ノ)

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

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

相关文章

初学python记录:力扣706. 设计哈希映射

题目&#xff1a; 不使用任何内建的哈希表库设计一个哈希映射&#xff08;HashMap&#xff09;。 实现 MyHashMap 类&#xff1a; MyHashMap() 用空映射初始化对象void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中&#x…

使用IT-Tools+Cpolar在Windows搭建自己的IT工具箱并实现远程在线使用

文章目录 1. 使用Docker本地部署it-tools2. 本地访问it-tools3. 安装cpolar内网穿透4. 固定it-tools公网地址 本篇文章将介绍如何在Windows上使用Docker本地部署IT- Tools&#xff0c;并且同样可以结合cpolar实现公网访问。 在前一篇文章中我们讲解了如何在Linux中使用Docker搭…

unity——Button组件单击双击长按功能

1.实现单击、双击、长按功能 using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; public class ButtonControl_Click_Press_Double : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler {publi…

【InternLM 实战营第二期笔记01】书生·浦语大模型全链路开源体系+InternLM2技术报告

本次课程链接在GitHub上&#xff1a;InternLM/Tutorial at camp2 (github.com) 第一次课程录播链接&#xff1a;书生浦语大模型全链路开源体系_哔哩哔哩_bilibili InternLM2技术报告&#xff1a;arxiv.org/pdf/2403.17297.pdf 一、书生浦语大模型全链路开源体系笔记 Intern…

强化学习-Reinforcement learning | RL

目录 什么是强化学习? 强化学习的应用场景 强化学习的主流算法 强化学习是机器学习的一种学习方式,它跟监督学习、无监督学习是对应的。本文将详细介绍强化学习的基本概念、应用场景和主流的强化学习算法及分类。 什么是强化学习? 强化学习并不是某一种特定的算法,而是…

消费增值新模式:让每一分钱都更有价值

亲爱的消费者们&#xff0c;大家好&#xff01;今天我想和大家探讨一种新颖的消费方式——消费增值&#xff0c;它让您的每一次消费都蕴含了额外的价值&#xff0c;让消费变得更加有意义。 在过往的消费观念里&#xff0c;我们往往只是简单地将钱花出去&#xff0c;购买所需的商…

Jmeter —— jmeter利用取样器中http发送请求

使用Jmeter发送HTTP请求 取样器是用来模拟用户操作&#xff0c;向服务器发送请求以及接收服务器的响应数 据的一类元件&#xff0c;其中HTTP请求取样器是用来模拟常用的http请求的 步骤如下&#xff1a; 步骤一&#xff1a;添加线程组 右击测试计划——添加——线程&#x…

ModuleNotFoundError: No module named ‘imageio‘ 解决方案

错误原因&#xff1a; 缺少imageio包导致 解决办法&#xff1a; 1、查看是否安装conda环境&#xff0c;如果未安装就先安装conda环境 conda --version 输出conda版本&#xff1a; 2、输入如下代码 conda config --add channels conda-forge conda install imgaug

带你追踪 ICASSP 2024会议现场 韩国夜景令人陶醉

会议之眼 快讯 昨天&#xff0c;2024年的ICASSP&#xff08;International Conference on Acoustics, Speech, and Signal Processing&#xff09;即国际声学、语音和信号处理会议已经在韩国首尔拉开帷幕&#xff01;吸引了众多热情的与会者&#xff01;本届ICASSP会议举办日期…

J垃圾回收

J垃圾回收 1 概述2 方法区的回收3 如何判断对象可以回收3.1 引用计数法3.2 可达性分析法 4 常见的引用对象4.1 软引用4.2 弱引用4.3 虚引用4.4 终结器引用 5 垃圾回收算法5.1 垃圾回收算法的历史和分类5.2 垃圾回收算法的评价标准5.3 标记清除算法5.4 复制算法5.5 标记整理算法…

【深入理解Java IO流0x0A】NIO实战-网络聊天室

本篇博客将进行NIO编程实战&#xff0c;实现一个简单聊天室。 我们来通过 SocketChannel 和 ServerSocketChannel 实现一个 0.1 版的聊天室&#xff0c;先说一下需求&#xff0c;比较简单&#xff0c;服务端启动监听客户端请求&#xff0c;当客户端向服务器端发送信息后&#x…

如何落地一个FaaS平台?

简介&#xff1a; 函数即服务&#xff08;FaaS&#xff09;作为云计算 2.0 时代重要的发展方向&#xff0c;能够从工程效率、可靠性、性能、成本等方面给开发者带来巨大的价值&#xff0c;尤其是能够极大地提升研发效率。因此&#xff0c;拥抱FaaS成为开发者关心的重要技术领域…