【零基础C语言】文件操作

目录

 理解文件操作

 什么是文件

 程序文件

 数据文件

 文件名字

 二进制文件和文本文件

 文件的打开和关闭

 文件的打开和关闭操作

实验1,打开一个文件并且输入26个字母 

打开读取文件text.txt ,并且将它拷贝进text_cpy.txt 

使用 fputs 和 fgets 函数 

使用 fprintf函数和 fscanf 函数 

有关于流的概念

 使用 fwrite 和 fread 函数

文件的随机读写 - 适用于二进制文件

 fseek 函数

ftell 函数 

 rewind 函数

 文件读取结束的判定

文件缓冲区


 

 理解文件操作

 我们为什么要使用文件呢?

 1.可以长久的存储我们的数据,没有文件存储我们输入的程序代码数据是在电脑内存中存储的,但是程序结束后,我们的数据也会清空,无法持久化保存

如以下代码:

int main()
{int a = 0; //创建变量ascanf("%d", &a); // 向a中输入数值return 0;
}

 我们可以通过内存窗口看见int变量a中存放我们输入的值,但是程序结束,数据会清空,我们需要重新输入

 什么是文件

 文件指的就是磁盘上的文件
 但是程序中我们的文件分为两种:程序文件,数据文件 - 按照功能划分

 

 程序文件


 struct 程序文件
{
    1.源程序文件(后缀为.c);
  2.目标文件(windows环境后缀为.obj);
  3.可执行文件(windows环境后缀为.exe);
};

 数据文件


 该文件的内容不一定是程序,也可以是运行时读写的数据,比如程序运⾏需要从中读取数据的⽂件,或者输出内容的文件。


 文件名字


 用于用户识别和使用,是文件的标识,这个相信大家都不陌生,我们在打开磁盘可以在上方的小方块看到当期文件的名字。

 二进制文件和文本文件

根据数据不同形式,我们将数据文件划分为二进制文件和文本文件

二进制文件:以二进制的形式存储,不用转换直接可以输出到外存

文本文件:字符一律以ASCLL码值存储,需要转换才可以输出到外存
 

 文件的打开和关闭

 在了解文件之前,我们需要认识一种抽象的概念 - 流
 什么是流呢?我们在生活中获取消息是从人流,网上等等渠道,同理计算机也是如此,
 我们把从键盘输入,文件读写和其他所有外部的数据糅合起来比作一条流淌着字符的数据河,
 而计算机则是从河中获取所需要的数据,读取它们,然后打开,再操作数据

 那么我们有可能有疑问了?我们平时键盘输入代码,屏幕打印字符数据好像并没有使用流啊
 这里我们就需要引入一个概念 - 标准流


 标准流在计算机C程序运行启动时就默认打开了3个流:

  1. stdin  - 标准输入流,获取我们输入的信息。
  2. stdout - 标准输出流,输出我们需要打印的信息
  3. stderr - 标准错误流。

 有了以上默认打开的流,我们使用scanf和printf就可以进行输入输出操作

 stdin,stdout,stderr 类型为 FILE* - 文件指针
 C语⾔中,就是通过FILE*的⽂件指针来维护流的各种操作的。

 文件指针

 我们在打开使用文件时,内存中会开辟一个文件信息区,这个信息区用来存放文件的相关
 信息,这些信息是保存在一个结构体变量中,取名为FILE。

 如vs2013编译环境中#include <stdio.h> 头文件种的类型申明。

struct _iobuf {char* _ptr;int _cnt;char* _base;int _flag;int _file;int _charbuf;int _bufsiz;char* _tmpfname;
};
typedef struct _iobuf FILE;

 借助这点我们可以定义一个指针变量指向该文件信息区,间接的找到该文件

 FILE* pf; 文件指针变量


 文件的打开和关闭操作

 在读写编辑文件之前,我们需要学会如何打开和关闭文件

 1.打开文件在编写程序时在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了指针和⽂件的关系。ANSIC规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件代码演示:打开文件:
FILE* fopen(const char* filename, const char* mode);关闭文件:
int fclose(FILE* stream);mode - 文件打开的模式,所有模式如下:"r"(只读) - 输入数据,打开一个存在的文本文件 - 如果文件不存在(出错)"w"(只写) - 输出数据,打开一个文本文件 - 如果文件不存在(创建一个新的文件)"a"(追加) - 向文本文件末尾添加数据 - 如果文件不存在(创建一个新的文件)"rb"(只读) - 输入数据,打开一个二进制文本文件 - 如果文件不存在(出错)"wb"(只写) - 输出数据,打开一个二进制文本文件 - 如果文件不存在(创建一个新的文件)"ab"(追加) - 向二进制文本文件末尾添加数据 - 如果文件不存在(创建一个新的文件)"r+"(读写) - 为了读和写,打开一个文本文件 - 如果文件不存在(出错)"w+"(读写)- 为了读和写,创建一个文本文件 - 如果文件不存在(创建一个新的文件)"a+"(读写)- 打开一个文本文件,在文件末尾进行读写 - 如果文件不存在(创建一个新的文件)"rb+"(读写)- 为了读和写,打开一个二进制文本文件 - 如果文件不存在(出错)"wb+"(读写)- 为了读和写,创建一个二进制文本文件 - 如果文件不存在(创建一个新的文件)"ab+"(读写)- 打开一个二进制文本文件,在文件末尾进行读写 - 如果文件不存在(创建一个新的文件)
int main()
{// 创建文本指针变量FILE* pf;//打开文件pf = fopen("text.txt", "r");//文件操作if (pf == NULL){//...perror("fopen");return 1;}else{fclose(pf);pf = NULL;}return 0;
}
 文件的顺序读写1.顺序读写函数介绍函数    功能          适用于fgetc - 字符输入函数 - 所有的输入流fputc - 字符输出函数 - 所有的输出流fgets - 文本行输入函数 - 所有输入流fputs - 文本行输入函数 - 所有输入流fscnaf - 格式化输入函数 - 所有输入流fprintf - 格式化输出函数 - 所有输出流fread   -   二进制输入   -   文件fwrite   -   二进制输出   -   文件

实验1,打开一个文件并且输入26个字母 

// 实验1,打开一个文件并且输入26个字母int main()
{// 打开并且写一个文件 - "w"FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 1;}//写文件int ch = 0;for (ch = 'a'; ch <= 'z'; ch++){fputc(ch, pf);}// 关闭文件fclose(pf);pf = NULL;return 0;
}

打开读取文件text.txt ,并且将它拷贝进text_cpy.txt 

// 打开读取文件text.txt ,并且将它拷贝进text_cpy.txtint main()
{// 打开文件FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen text.txt");return 1;}FILE* pw = fopen("text_cpy.txt", "w");if (pw == NULL){perror("fopen text_cpy.txt");fclose(pf);pf = NULL;return 1;}// 读取并且写入int ch = 0;while ((ch = fgetc(pf)) != EOF){fputc(ch, pw);}// 关闭文件fclose(pf);pf = NULL;fclose(pw);pw = NULL;return 0;
}

使用 fputs 和 fgets 函数 

//使用 fputs 和 fgets 函数int main()
{// 打开文件FILE* pf = fopen("fputs.txt", "w");if (pf == NULL){perror("fopen fputs.txt");return 1;}// 使用 fputs函数写文件// 函数原型// int fputs(const char* str, FILE * stream);// const char* str 传入读取的字符串的首地址// FILE* stream 将读取的内容写入文件中char ch[] = "ouyang is cool\n";fputs(ch, pf);fputs("hello ouyang", pf);// 关闭文件fclose(pf);pf = NULL;return 0;
}int main()
{// 打开文件FILE* pf = fopen("fputs.txt", "r");if (pf == NULL){perror("fopen fputs.txt");return 1;}// 使用 fgets函数读取文件// 函数原型// char* fgets(char* str, int num, FILE * stream);// char* str 函数将读取到的数据返回char*类型指针的首地址// int num  读取的长度// FILE* stream 读取文件的地址// 如果读取失败会返回NULLchar ch[20] = { 0 };// 单个读取/*fgets(ch, 20, pf);printf("%s", ch);*/// 连续读取while (fgets(ch, 20, pf) != NULL){printf("%s", ch);}// 关闭文件fclose(pf);pf = NULL;return 0;
}

使用 fprintf函数和 fscanf 函数 

typedef struct stu
{char name[20];int age;char sex[5];
}S;int main()
{// 打开文件并且写入FILE* pf = fopen("fprintf.txt", "w");if (pf == NULL){perror("fopen fprintf.txt");return 1;}// 写入S s = { "欧阳",20,"男" };fprintf(pf, "%s %d %s", s.name, s.age, s.sex);//关闭文件fclose(pf);pf = NULL;return 0;
}
typedef struct stu
{char name[20];int age;char sex[5];
}S;
int main()
{// 打开文件并且写入FILE* pf = fopen("fprintf.txt", "r");if (pf == NULL){perror("fopen fprintf.txt");return 1;}// 读取文件S s = {0};fscanf(pf, "%s %d %s", s.name, &(s.age), s.sex);// 打印在屏幕上观察printf("%s %d %s", s.name, s.age, s.sex);//关闭文件fclose(pf);pf = NULL;return 0;
}

有关于流的概念

  • stdin - 标准输入流,获取我们输入的信息。
  • stdout - 标准输出流,输出我们需要打印的信息
  • fgetc, fgets, fputc, fputs, fscanf, fprintf - 适用于所有流
  • fread, fwrite - 适用于文件流
// 使用标准流int main()
{fputc('a', stdout);return 0;
}

 使用 fwrite 和 fread 函数

 

int main()
{// 以二进制的形式写文件FILE* pf = fopen("fwrite.txt", "wb");if (pf == NULL){perror("fopen fwrite.txt");return 1;}// 写二进制文件// fwrite 函数// 函数原型:// size_t fwrite(const void* ptr, size_t size, size_t count, FILE * stream);// const void* ptr - 指向要写入文件的数据// size_t size - 指向数据类型的大小// siez_t count -指向数据的数量// FILE * stream - 写入的文件指针int arr[] = { 1,2,3,4,5 };int sz = sizeof(arr) / sizeof(arr[0]);fwrite(arr, sizeof(arr[0]), sz, pf);// 关闭文件fclose(pf);pf = NULL;return 0;
}

int main()
{// 打开文件FILE* pf = fopen("fwrite.txt", "rb");if (pf == NULL){perror("fopen fwrite.txt");return 1;}// 读取文件// fread 函数// 函数原型:// size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );// const void* ptr - 指向要读取文件的数据// size_t size - 指向数据类型的大小// siez_t count -指向数据的数量// FILE * stream - 要读取的文件指针int arr[5] = { 0 };fread(arr, sizeof(arr[0]), 5, pf);int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr[i]);}// 关闭文件fclose(pf);pf == NULL;return 0;
}

文件的随机读写 - 适用于二进制文件

 fseek 函数

// 函数原型:
// int fseek ( FILE * stream, long int offset, int origin );// FILE * stream - 指向FILE*文件对象的指针
// long int offset - 偏移的字节数
// int origin - 参考位置
// 如:
//SEEK_SET	文件开头
//SEEK_CUR	文件指针的当前位置
//SEEK_END	文件末尾*int main()
{// 读写文件FILE* pf = fopen("fseek.txt", "wb");if (pf == NULL){perror("fopen fseek.txt");return 1;}// 读写fputs("hello ouyang",pf);fseek(pf, 6, SEEK_SET);fputs("to ", pf);// 关闭文件fclose(pf);pf == NULL;return 0;
}int main()
{// 打开并且读文件FILE* pf = fopen("fseek.txt", "rb");if (pf == NULL){perror("fopen fseek.txt");return 1;}// 读取文件char ch[200] = { 0 };while (fgets(ch, 50, pf) != NULL){printf("%s\n", ch);}// 关闭文件fclose(pf);pf = NULL;return 0;
}

ftell 函数 

// 函数原型:
// long int ftell ( FILE * stream );int main()
{// 读写文件FILE* pf = fopen("fseek.txt", "rb");if (pf == NULL){perror("fopen fseek.txt");return 1;}// ftell 函数的使用fseek(pf, 6, SEEK_SET);long size = ftell(pf);printf("Size of myfile.txt: %ld bytes.\n", size);// 关闭文件fclose(pf);pf == NULL;return 0;
}

 rewind 函数

// 函数原型:
// void rewind ( FILE * stream );int main()
{// 打开文件并且写入FILE* pf = fopen("myfile.txt", "w+");char buffer[27];int n = 0;for (n = 'A'; n <= 'Z'; n++)fputc(n, pf); //写入之后的光标在最后rewind(pf); // 回调光标fread(buffer, 1, 26, pf); // 将文件中的数据读取到字符数组中//关闭文件fclose(pf);pf = NULL;// 打印观察buffer[26] = '\0'; // 方便输出字符串,将最后一位设置为'\0'printf(buffer); // 打印return 0;
}

 文件读取结束的判定

 feof 函数
 注意:该函数不可以通过该函数的返回值来直接判断文件的结束

 作用是当文件结束时,判断是读取失败的原因,还是遇到文件结尾结束

⽂本⽂件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
• fgetc 判断是否为 EOF 
• fgets 判断返回值是否为 NULL 

int main()
{int c = 0; // 注意:int,⾮char,要求处理EOFFILE* fp = fopen("test.txt", "r");if (fp==NULL) {perror("File opening failed");return 1;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环{putchar(c);}//判断是什么原因结束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);fp = NULL;
}

文件缓冲区

我们在程序中向文件中写入数据不会是有一条写一条,打个比方说:一个学生
问问题不是说问完一个过几分钟又问一个,则会导致老师无法为其他同学解答
问题,操作系统也是如此,操作系统不光是为了写入文件而服务的,所有这个学生
就会将问题攒着,直到一定的数量就可以去问老师,同理我们写入的文件也是如此
而存放这些数据的空间就叫做文件缓冲区

源代码地址:text_2024_3_26 · 6988b68 · 阳区欠/C语言学习路程 - Gitee.com

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

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

相关文章

【计算机网络】IP 协议

网络层IP协议 一、认识 IP 地址二、IP 协议报头格式三、网段划分1. 初识子网划分2. 理解子网划分3. 子网掩码4. 特殊的 IP 地址5. IP 地址的数量限制6. 私有 IP 地址和公网 IP 地址7. 理解全球网络&#xff08;1&#xff09;理解公网&#xff08;2&#xff09;理解私网&#xf…

华为汽车图谱

极狐 极狐&#xff08;ARCFOX&#xff09;是由北汽、华为、戴姆勒、麦格纳等联合打造。总部位于北京蓝谷。 问界 华为与赛力斯&#xff08;东风小康&#xff09;合作的成果。 阿维塔 阿维塔&#xff08;AVATR&#xff09;是由长安汽车、华为、宁德时代三方联合打造。公司总部位…

canal: 连接kafka (docker)

一、确保mysql binlog开启并使用ROW作为日志格式 docker 启动mysql 5.7配置文件 my.cnf [mysqld] log-binmysql-bin # 开启 binlog binlog-formatROW # 选择 ROW 模式 server-id1一定要确保上述两个值一个为ROW&#xff0c;一个为ON 二、下载canal的run.sh https://github.c…

一周学会Django5 Python Web开发-Django5模型定义

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计41条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

26. BI - PageRank 拓展以及如何利用 networkx 来分析希拉里丑闻

本文为 「茶桁的 AI 秘籍 - BI 篇 第 26 篇」 Hi, 我是茶桁. 上节课咱们讲解了 PageRank 的两种模型, 并分别做了代码上的演示. 这节课, 让我们来看看 PageRank 的影响力及其应用. PageRank 已经超越了原来提出来的模型, 因为 PageRank 的影响力影响到了后续很多的一些模型, …

我的创作纪念日 ---- 2024/3/26

前言 2024.3.26是我在CSDN成为创作者的第128天&#xff0c;也是我第一次真正在网上创作的第128天 当我还在日常创作时&#xff0c;突然发现我收到了一封信 我想我可以分享一下这段时间的感想以及收获 机缘 在CSDN的这段时间里&#xff0c;我学习到了很多知识&#xff0c;也…

数据结构——链表(单链表)

大家好&#xff0c;又是我&#xff08;小锋&#xff09;&#xff0c;今天给大家带了一个比较有挑战的章节&#xff08;链表&#xff09;&#xff0c;但是不用担心&#xff0c;小锋会陪大家一起度过。 顺序表的思考与问题 1. 中间/头部的插入删除&#xff0c;时间复杂度为O(N) …

【python】flask模板渲染引擎Jinja2,通过后端数据渲染前端页面

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Spring Cloud 八:微服务架构中的数据管理

Spring Cloud 一&#xff1a;Spring Cloud 简介 Spring Cloud 二&#xff1a;核心组件解析 Spring Cloud 三&#xff1a;API网关深入探索与实战应用 Spring Cloud 四&#xff1a;微服务治理与安全 Spring Cloud 五&#xff1a;Spring Cloud与持续集成/持续部署&#xff08;CI/C…

Eladmin-jpa基于SpringBoot和Vue的前后端分离后台管理系统​

在当今快速发展的软件开发领域&#xff0c;前后端分离的架构模式已经成为主流。这种架构模式不仅可以提高开发效率&#xff0c;还能使系统更加易于维护和扩展。Eladmin-jpa是一个基于Spring Boot 2.6.4、Spring Boot Jpa、JWT、Spring Security、Redis和Vue的前后端分离的后台管…

JS等比压缩图片方法

AI给出来的答案&#xff0c;AI真的能改变世界&#xff0c;以后程序员这个职业真的有可能不存在了。 function compressImage(image, callback) {// 创建一个 canvas 元素const canvas document.createElement(canvas);canvas.width 48;canvas.height 48;// 获取 canvas 的绘…

[WTL/Win32]_[初级]_[如何设置ListView的列宽不出现水平滚动条]

场景 开发WTL/Win32的程序时&#xff0c;经常会用到表格控件CListViewCtrl。这个控件需要设置列的宽度&#xff0c;当用完100%的宽度来平均分配给列宽时&#xff0c;一加载数据多&#xff0c;就会出现垂直滚动条后&#xff0c;水平滚动条也会同时出现的问题。怎么设置才能让水…

【研发日记】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…

单链表专题(上)(顺序表链表线性表)

在开始之前思考一个顺序表的问题 1. 中间/头部的插⼊删除&#xff0c;时间 复杂度为O(N) 2. 增容需要申请新空间&#xff0c;拷⻉数据&#xff0c;释放旧空间。会有不⼩的消耗。 3. 增容⼀般是呈2倍的增⻓&#xff0c;势必会有⼀定的空间浪费。例如当前容量为100&#xff0c;…

订单系统-RPC快速入门

RPC快速入门 概述 关于rpc&#xff0c;只需要知道他是一种协议&#xff0c;项目之间能够远程调用函数。 快速入门 我们前边下载好的两个包&#xff0c;在idea中打开之后&#xff0c;我们创建这么几个文件夹。 至于是干什么的&#xff0c;以后细说。创建好之后我们在produc…

从零开始搭建游戏服务器 第七节 创建GameServer

目录 前言正文创建GameServer模块修改配置创建NettyClient连接到登录服登录服修改创建协议游戏服注册到登录服 总结 前言 上一节我们使用自定义注解反射简化了协议解包和逻辑处理分发流程。 那么到了这里登录服登录服的架构已经搭建的差不多了&#xff0c;一些比较简单的、并发…

使用 Outline 构建 企业 or 个人 知识库面临的问题

前不久&#xff0c;我写了一篇文章&#xff0c;介绍《如何在本地部署安装 Outline》&#xff0c;我之所以写这篇文章&#xff0c;主要原因是我最近需要做一个项目&#xff0c;使用 Outline 来构建一个公司级知识库。所以我需要在本地先搭建一个&#xff0c;来撰写一些前期的文档…

【环境配置】Ubuntu MySQL 8.0.28 安装并允许外部客户端连接

文章目录 MySQL 安装步骤配置 MySQL Server 允许外部连接 MySQL 安装步骤 步骤一&#xff1a;在 MySQL 官网找到 apt 仓库&#xff0c;下载最新的仓库 点击 Download&#xff1a; 输入如下命令&#xff1a; sudo wget -c https://dev.mysql.com/get/mysql-apt-config_0.8…

2014年认证杯SPSSPRO杯数学建模A题(第一阶段)轮胎的花纹全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 A题 轮胎的花纹 原题再现&#xff1a; 轮胎被广泛使用在多种陆地交通工具上。根据性能的需要&#xff0c;轮胎表面常会加工出不同形状的花纹。在设计轮胎时&#xff0c;往往要针对其使用环境&#xff0c;设计出相应的花纹形状。   第一阶段问…

JVM(三)——字节码技术

三、字节码技术 1、类文件结构 一个简单的 HelloWorld.java package com.mysite.jvm.t5; // HelloWorld 示例 public class HelloWorld {public static void main(String[] args) {System.out.println("hello world");} }执行 javac -parameters -d . HellowWorld.…