C语言之文件操作(下)

C语言之文件操作(下)

文章目录

  • C语言之文件操作(下)
    • 1. 文件的顺序读写
      • 1.1 文件的顺序读写函数
        • 1.1.1 字符输入/输出函数(fgetc/fputc)
        • 1.1.2 ⽂本⾏输⼊/输出函数(fgets/fputs)
        • 1.1.3 格式化输入/输出函数(fscanf/fprintf)
        • 1.1.4 二进制输入/输出(fread/fwrite)
    • 2. 文件的随机读写
      • 2.1 fseek
      • 2.2 ftell
      • 2.3 rewind
    • 3. 文件读取结束的判定
      • 3.1 feof/ferror
      • 4.文件缓冲区

  在上篇博文中介绍到了文件的打开fopen和关闭fclose以及文件指针FILE*,在这边博文中将介绍文件的读写

1. 文件的顺序读写

1.1 文件的顺序读写函数

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

所有输入流/所有输出流:适⽤于标准输⼊/输出流和其他输⼊/输出流(如⽂件输⼊/输出流)

1.1.1 字符输入/输出函数(fgetc/fputc)

字符输入/输出函数:用于单个字符的输入/输出

fgetc():从文件中读取字符

int fgetc ( FILE * stream );

fputc():将字符写入文件

int fputc ( int character, FILE * stream );

示例如下:

#include <stdio.h>
#include <string.h>int main()
{FILE* pfwrite = fopen("test.txt", "w"); //以只写的方式打开文件if (pfwrite == NULL)  //判断是否打开成功{perror("fopen");  //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}fputc('a', pfwrite);   //将‘a’放入文件fclose(pfwrite);      //关闭文件pfwrite = NULL;       //文件指针置NULLFILE* pfread = fopen("test.txt", "r"); //以只读的方式打开文件if (pfread == NULL)  //判断是否打开成功{perror("fopen");   //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}int ch = fgetc(pfread);  //将读取的字符存放到 chprintf("%c", ch);       //打印chfclose(pfread);        //关闭文件pfread = NULL;         //文件指针置NULLreturn 0;
}

注:每次打开同一个文件时,无论是否有内容写入,文件的内容会被覆盖

1.1.2 ⽂本⾏输⼊/输出函数(fgets/fputs)

⽂本⾏输⼊/输出函数:用于字符串的输入/输出

fgets():从文件中读取 num 个长度的字符

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

fputs():将字符串写入文件

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

示例如下:

#include <stdio.h>
#include <string.h>int main()
{FILE* pfwrite = fopen("test.txt", "w"); //以只写的方式打开文件if (pfwrite == NULL)  //判断是否打开成功{perror("fopen");  //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}fputs("abcdef\n", pfwrite);   //将"abcdef\n"放入文件fclose(pfwrite);      //关闭文件pfwrite = NULL;       //文件指针置NULLFILE* pfread = fopen("test.txt", "r"); //以只读的方式打开文件if (pfread == NULL)  //判断是否打开成功{perror("fopen");   //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}char str[20] = { 0 };fgets(str,5,pfread);  //将读取的字符存放到 strprintf("%s\n", str);   //打印strfclose(pfread);        //关闭文件pfread = NULL;         //文件指针置NULLreturn 0;
}

注:当我们写入一串字符串时,如果不主动换行,会在同一行写入,所有如果我们要换行的话,我们可以在输入的字符串中加上个\n

1.1.3 格式化输入/输出函数(fscanf/fprintf)

格式化输入/输出函数:用于按格式将数据输出/输入文件

fscanf():将数据按格式读取文件

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

fprintf():将数据按格式的写入文件

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

fscanf()/fprintf()和正常的scanf()/printf()用法一样,不过是从文件中读取/写入

示例如下:

#include <stdio.h>
#include <string.h>struct Stu
{char name[20];int age;float score;
};
int main()
{struct Stu s1 = { "zhangsan",18,92.3f };struct Stu s2 = { 0 };FILE* pfwrite = fopen("test.txt", "w"); //以只写的方式打开文件if (pfwrite == NULL)  //判断是否打开成功{perror("fopen");  //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}fprintf(pfwrite,"%s %d %f",s1.name,s1.age,s1.score);   //将s1中的内容放入文件fclose(pfwrite);      //关闭文件pfwrite = NULL;       //文件指针置NULLFILE* pfread = fopen("test.txt", "r"); //以只读的方式打开文件if (pfread == NULL)  //判断是否打开成功{perror("fopen");   //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}fscanf(pfread, "%s %d %f", s2.name, &(s2.age), &(s2.score));  //将读取的字符存放到 s2fprintf(stdout, "%s %d %.2f", s2.name, s2.age, s2.score);    //使用fprintf将s2中的内容打印到屏幕fclose(pfread);        //关闭文件pfread = NULL;         //文件指针置NULLreturn 0;
}

注:stdout为标准输出流(屏幕)stdin为标准输入流(键盘)stderr为标准错误流(屏幕)

1.1.4 二进制输入/输出(fread/fwrite)

二进制输入/输出:将二进制输入/输出到文件(只针对文件)

fread():从文件中读取count个大小为size的数据,存放在ptr指向的数据

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

fwrite():将ptr指向的数据,写入count个大小为size到文件

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

示例如下:

#include <stdio.h>
#include <string.h>int main()
{int a = 10000;int b = 0;FILE* pfwrite = fopen("test.txt", "wb"); //以只写的方式打开文件if (pfwrite == NULL)  //判断是否打开成功{perror("fopen");  //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}fwrite(&a,sizeof(int),1,pfwrite);    //将a中的数据以二进制形式写入文件fclose(pfwrite);      //关闭文件pfwrite = NULL;       //文件指针置NULLFILE* pfread = fopen("test.txt", "rb"); //以只读的方式打开文件if (pfread == NULL)  //判断是否打开成功{perror("fopen");   //如果打开失败根据错误码打印错误信息return 1;         //关闭程序}fread(&b,sizeof(int),1,pfread);  //将读取的数据放到 bprintf("%d", b);fclose(pfread);                //关闭文件pfread = NULL;               //文件指针置NULLreturn 0;
}

注:写入记事本中的二进制数据是不能直接看出来的,但是无论放入还是取出来都是10000,所以不用过度关注

2. 文件的随机读写

在文件中,写入一个数据,文件指针就向后走,那我们要如何在指定位置写入或读取数据呢?
下面来介绍三个函数fseek ftell rewind

2.1 fseek

fseek:为根据文件指针的位置,向前或向后移动文字指针

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

offset:为偏移量,向前或向后或不动
origin :为文件的位置

关于origin C语言中规定有三个取值

  1. SEEK_SET 文件的起始位置
  2. SEEK_CUR 文件指针的当前位置
  3. SEEK_END 文件的末尾

示例如下:

#include <stdio.h>
#include <string.h>int main()
{FILE* pf = fopen("test.txt", "r");if (!pf){perror("fopen");return -1;}//假设文件中已经有字符了 "abcdef"int ch = fgetc(pf);    printf("%c\n", ch);   //打印'a'ch = fgetc(pf);printf("%c\n", ch);    //打印'b'ch = fgetc(pf);printf("%c\n", ch);   //打印'c'ch = fgetc(pf);printf("%c\n", ch);   //打印'd'//三种方式都可以//fseek(pf, -4, SEEK_CUR);//当前位置'd',倒退4个字节,'a'//fseek(pf, 0, SEEK_SET);//当前位置'd',文件起始位置fseek(pf, -6, SEEK_END);//当前位置'd',文件末尾位置,倒退6个字节'a'ch = fgetc(pf);printf("%c\n", ch);  //打印'a'fclose(pf);pf = NULL;return 0;
}

2.2 ftell

ftell:为相对文件起始位置的偏移量

long int ftell ( FILE * stream );
#include <stdio.h>
#include <string.h>int main()
{FILE* pf = fopen("test.txt", "r");if (!pf){perror("fopen");return -1;}//假设文件中已经有字符了 "abcdef"int ch = fgetc(pf);    printf("%c\n", ch);   //打印'a'ch = fgetc(pf);printf("%c\n", ch);    //打印'b'ch = fgetc(pf);printf("%c\n", ch);   //打印'c'ch = fgetc(pf);printf("%c\n", ch);   //打印'd'ch = fgetc(pf);printf("%c\n", ch);  //打印'e'int ret = ftell(pf);  //打印了5次,相对文件起始位置5个字节printf("%d",ret);  fclose(pf);pf = NULL;return 0;
}

2.3 rewind

frewind:为回到文件的起始位置

void rewind ( FILE * stream );
#include <stdio.h>
#include <string.h>int main()
{FILE* pf = fopen("test.txt", "r");if (!pf){perror("fopen");return -1;}//假设文件中已经有字符了 "abcdef"int ch = fgetc(pf);    printf("%c\n", ch);   //打印'a'ch = fgetc(pf);printf("%c\n", ch);    //打印'b'ch = fgetc(pf);printf("%c\n", ch);   //打印'c'ch = fgetc(pf);printf("%c\n", ch);   //打印'd'rewind(pf);ch = fgetc(pf);printf("%c\n", ch);  //打印'a'fclose(pf);pf = NULL;return 0;
}

3. 文件读取结束的判定

3.1 feof/ferror

在文件读取过程中,不能使用feof函数的返回值直接判断文件是否结束

feof:为在文件读取结束的时候,判断读取结束的原因是否是遇到文件尾结束
ferror:为在文件读取结束的时候,判断读取结束的原因是否是遇到错误结束

使用feof判断不同文件读取结束的方法

  1. 文本文件:判断返回值是否为EOF或者NULL
    例如:
    fgetc判断返回值是否为EOF
    fgets判断返回值是否为NULL
  2. 二进制文件:判断返回值是否小于实际读取个数
    例如:
    fread判断返回值是否为实际读取的个数

feof/ferror使用示例如下:
文本文件:

#include <stdio.h>
#include <string.h>int main(void)
{int c = 0;FILE* fp = fopen("testc.txt", "r");if (!fp) {perror("fopen");return 1;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) {putchar(c);}//判断是什么原因结束的if (ferror(fp))perror("error"); //文件遇到错误结束,则打印错误信息else if (feof(fp))printf("success"); //文件正常结束,成功则打印successfclose(fp);
}

二进制文件:

#include <stdio.h>
int main()
{int a = 10;int b = 0;FILE* pf = fopen("test.txt", "rb");if (pf == NULL){perror("fopen");return 1;}//fwrite(&a, sizeof a, 1, pf);size_t ret = fread(&b, sizeof b, 5, pf);if (ret == 5) //当返回值等于读取的个数表示成功{printf("success");}else{if (ferror(pf))   //判断是否遇到错误{perror("ferror");}else if(feof(pf)) //判断是否文件结束{printf("feof");}}fclose(pf);pf = NULL;return 0;
}

4.文件缓冲区

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

注:当我们写入或读取文件的时候,并不是立刻完成的,而且将要写入或读取的数据放在文件缓冲区,等缓冲区满了或者刷新缓冲区时(fflush fclose),才会读取或写入数据

#include <stdio.h>
#include <windows.h>
//VS2022 WIN11环境测试
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)//注:fflush 在⾼版本的VS上不能使⽤了printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭⽂件的时候,也会刷新缓冲区pf = NULL;return 0;
}

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

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

相关文章

Spring Boot之自定义starter

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Spring Boot的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. starter是什么 二.为什么要使…

大模型应用_PrivateGPT

https://github.com/imartinez/privateGPT 1 功能 整体功能&#xff0c;想解决什么问题 搭建完整的 RAG 系统&#xff0c;与 FastGPT相比&#xff0c;界面比较简单。但是底层支持比较丰富&#xff0c;可用于知识库的完全本地部署&#xff0c;包含大模型和向量库。适用于保密级…

SWPU NSS新生赛

&#x1f60b;大家好&#xff0c;我是YAy_17&#xff0c;是一枚爱好网安的小白&#xff0c;正在自学ing。 本人水平有限&#xff0c;欢迎各位大佬指点&#xff0c;一起学习&#x1f497;&#xff0c;一起进步⭐️。 ⭐️此后如竟没有炬火&#xff0c;我便是唯一的光。⭐️ 最近…

万界星空科技AI低代码云MES系统

在企业生产管理过程中&#xff0c;从市场、生产现场到产品交付&#xff0c;生产制造行业都面临着诸多挑战&#xff0c;比如&#xff1a; 订单排产难度大&#xff1a;订单混乱&#xff0c;常漏排产、错排产&#xff1b;产能不明晰&#xff0c;无法承诺交期&#xff0c;常丢单&a…

流程控制之条件判断

目录 流程控制之条件判断 2.1.if语句语法 2.1.1单分支结构 2.1.2双分支结构 2.1.3多分支结构 2.2.案例 例一: 例2: 例3: 例4: 例5: 例6: 例7: 例8: 例9: 2.3.case多条件判断 2.3.1.格式 2.3.2.执行过程 例10: 流程控制之条件判断 2.1.if语句语法 2.1.1单分…

ArcGIS for Android开发引入arcgis100.15.2

最后再点击同步即可&#xff01;&#xff01;&#xff01;

oracle aq java jms使用(数据类型为XMLTYPE)

记录一次冷门技术oracle aq的使用 版本 oracle 11g 创建用户 -- 创建用户 create user testaq identified by 123456; grant connect, resource to testaq;-- 创建aq所需要的权限 grant execute on dbms_aq to testaq; grant execute on dbms_aqadm to testaq; begindbms_a…

基于Spring Boot、Mybatis、Redis和Layui的企业电子招投标系统源码实现与立项流程

招投标管理系统是一款适用于招标代理、政府采购、企业采购和工程交易等领域的企业级应用平台。该平台以项目为主线&#xff0c;从项目立项到项目归档&#xff0c;实现了全流程的高效沟通和协作。通过该平台&#xff0c;用户可以实时共享项目数据信息&#xff0c;实现规范化管理…

【数据结构入门精讲 | 第一篇】打开数据结构之门

数据结构与算法是计算机科学中的核心概念&#xff0c;也与现实生活如算法岗息息相关。鉴于全网数据结构文章良莠不齐且集成度不高&#xff0c;故开设本专栏&#xff0c;为初学者提供指引。 目录 基本概念数据结构为何面世算法基本数据类型抽象数据类型使用抽象数据类型的好处 数…

微信小程序:模态框(弹窗)的实现

效果 wxml <!--新增&#xff08;点击按钮&#xff09;--> <image classimg src"{{add}}" bindtapadd_mode></image> <!-- 弹窗 --> <view class"modal" wx:if"{{showModal}}"><view class"modal-conten…

消息队列(MQ)

对于 MQ 来说&#xff0c;不管是 RocketMQ、Kafka 还是其他消息队列&#xff0c;它们的本质都是&#xff1a;一发一存一消费。下面我们以这个本质作为根&#xff0c;一起由浅入深地聊聊 MQ。 01 从 MQ 的本质说起 将 MQ 掰开了揉碎了来看&#xff0c;都是「一发一存一消费」&…

java实现冒泡排序及其动图演示

冒泡排序是一种简单的排序算法&#xff0c;它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。重复这个过程直到整个数列都是按照从小到大的顺序排列。 具体步骤如下&#xff1a; 比较相邻的两个元素&#xff0c;如果前…

世界5G大会

会议名称:世界 5G 大会 时间:2023 年 12 月 5 日-12 月 8 日 地点:河南郑州 一、会议简介 世界 5G 大会,是由国务院批准,国家发展改革委、科技部、工 信部与地方政府共同主办,未来移动通信论坛联合属地主管厅局联合 承办,邀请全球友好伙伴共同打造的全球首个 5G 领域…

Spring Boot 3 整合 WebSocket (STOMP协议) 和 Vue 3 实现实时通信

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

家政服务小程序预约上门,让服务更便捷

随着人们生活节奏的加快&#xff0c;家政服务行业越来越受到人们的欢迎。为了满足市场需求&#xff0c;提高服务质量&#xff0c;家政公司需要开发一款预约上门的家政服务小程序。本文将详细介绍如何制作一个预约上门的家政服务小程序。 一、登录乔拓云网后台 首先&#xff0c…

基于vue实现的疫情数据可视化分析及预测系统-计算机毕业设计推荐django

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Appium自动化常用adb操作封装

一、前置说明 在Appium自动化中&#xff0c;经常需要使用adb命令与设备进行交互&#xff0c;所以有必要把常用的adb操作封装成一个类 二、代码实现 import os import platform import re import subprocessfrom common import path from common.exception import AndroidSDK…

语音识别功能测试:90%问题,可以通过技术解决

现在市面上的智能电子产品千千万&#xff0c;为了达到人们使用更加方便的目的&#xff0c;很多智能产品都开发了语音识别功能&#xff0c;用来语音唤醒进行交互&#xff1b;另外&#xff0c;各大公司也开发出来了各种智能语音机器人&#xff0c;比如小米公司的“小爱”&#xf…

DHCP—动态主机配置协议

动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;是RFC 1541&#xff08;已被RFC 2131取代&#xff09;定义的标准协议&#xff0c;该协议允许服务器向客户端动态分配IP地址和配置信息。 DHCP协议支持C/S&#x…

外汇天眼:Coinbase国际交易所将启动现货市场

Coinbase宣布了Coinbase国际交易所扩张的下一阶段——退出符合条件客户的非美国现货市场。 这一最新发展旨在满足Coinbase全球用户群体的独特需求和需求&#xff0c;同时强化其扩大国际访问可信产品和服务的战略使命。 Coinbase国际交易所现货交易的推出和扩展将分阶段进行。1…