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;       //文件指针置NULL
	FILE* pfread = fopen("test.txt", "r"); //以只读的方式打开文件
	if (pfread == NULL)  //判断是否打开成功
	{
		perror("fopen");   //如果打开失败根据错误码打印错误信息
		return 1;         //关闭程序
	}
	int ch = fgetc(pfread);  //将读取的字符存放到 ch
	printf("%c", ch);       //打印ch
	fclose(pfread);        //关闭文件
	pfread = NULL;         //文件指针置NULL
	return 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;       //文件指针置NULL
	FILE* pfread = fopen("test.txt", "r"); //以只读的方式打开文件
	if (pfread == NULL)  //判断是否打开成功
	{
		perror("fopen");   //如果打开失败根据错误码打印错误信息
		return 1;         //关闭程序
	}
	char str[20] = { 0 };
    fgets(str,5,pfread);  //将读取的字符存放到 str
	printf("%s\n", str);   //打印str
	fclose(pfread);        //关闭文件
	pfread = NULL;         //文件指针置NULL
	return 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;       //文件指针置NULL
	FILE* pfread = fopen("test.txt", "r"); //以只读的方式打开文件
	if (pfread == NULL)  //判断是否打开成功
	{
		perror("fopen");   //如果打开失败根据错误码打印错误信息
		return 1;         //关闭程序
	}
	fscanf(pfread, "%s %d %f", s2.name, &(s2.age), &(s2.score));  //将读取的字符存放到 s2
	fprintf(stdout, "%s %d %.2f", s2.name, s2.age, s2.score);    //使用fprintf将s2中的内容打印到屏幕
	fclose(pfread);        //关闭文件
	pfread = NULL;         //文件指针置NULL
	return 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;       //文件指针置NULL
	FILE* pfread = fopen("test.txt", "rb"); //以只读的方式打开文件
	if (pfread == NULL)  //判断是否打开成功
	{
		perror("fopen");   //如果打开失败根据错误码打印错误信息
		return 1;         //关闭程序
	}
	fread(&b,sizeof(int),1,pfread);  //将读取的数据放到 b
	printf("%d", b);
	fclose(pfread);                //关闭文件
	pfread = NULL;               //文件指针置NULL
	return 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 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOF
	while ((c = fgetc(fp)) != EOF) 
	{
		putchar(c);
	}
	//判断是什么原因结束的
	if (ferror(fp))
		perror("error"); //文件遇到错误结束,则打印错误信息
	else if (feof(fp))
		printf("success"); //文件正常结束,成功则打印success
	fclose(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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL练题笔记-高级字符串函数 / 正则表达式 / 子句-简单3题

这个系列先写了三题&#xff0c;比较简单写在一起。 1.修复表中的名字相关的表和题目如下 看题目就知道是有关字符串函数的&#xff0c;于是在书里查询相关的函数&#xff0c;如下图&#xff0c;但是没有完全对口的函数&#xff0c;所以我还是去百度了。 然后发现结合上面的4个…

多层感知机

目录 一、感知机 1、相关概念介绍 2、&#xff08;单层&#xff09;感知机存在的问题 3、总结 二、多层感知机&#xff08;MLP&#xff09; 1、多层感知机思路 2、激活函数 3、常见的激活函数 4、多类分类 4、总结 三、多层感知机从零开始实现 1、读取数据集 2、初…

[Kubernetes]2. k8s集群中部署基于nodejs golang的项目以及Pod、Deployment详解

一. 创建k8s部署的镜像 1.部署nodejs项目 (1).上传nodejs项目到节点node1 (2).压缩nodejs项目 (3).构建nodejsDockerfile 1).创建nodejsDockerfile 具体可参考:[Docker]十.Docker Swarm讲解,在/root下创建nodejsDockerfile,具体代码如下: FROM node #把压缩文件COPY到镜像的…

掌握iText:轻松处理PDF文档-高级篇-添加页眉和页脚

推荐语 本文介绍了如何使用iText编程库为PDF文档添加自定义的页眉和页脚。通过指定位置、大小、字体和颜色等属性&#xff0c;你可以将文本、图像或其他元素添加到每一页的固定位置&#xff0c;实现专业、可读的自定义页眉和页脚效果。这对于需要批量处理大量PDF文档或需要更精…

modelbox线程爆满宕机bug

序 该bug的解决需要特别感谢张同学。有了大佬的帮助&#xff0c;这个bug才得以解决。 问题现象 modelbox可以进行模型推理&#xff0c;但压测一段时间后&#xff0c;modelbox会宕机&#xff0c;并发生段错误。 “libgomp: Thread creation failed: Resource temporarily una…

TCP/IP详解——ICMP协议,Ping程序,Traceroute程序,IP源站选路选项

文章目录 一、ICMP 协议1. ICMP 概念2. ICMP 重定向3. ICMP 差错检测4. ICMP 错误报告/差错报文5. ICMP 差错报文的结构6. ICMP 源站抑制差错7. ICMP 数据包格式8. ICMP 消息类型和编码类型9. ICMP 应用-Ping10. ICMP 应用-Tracert11. BSD 对 ICMP 报文的处理12. 总结 PING 程序…

数据结构:队列

数据结构&#xff1a;队列 文章目录 数据结构&#xff1a;队列1.队列常用操作&#xff1a;2.队列的实现3.队列典型应用 ***「队列 queue」是一种遵循先入先出规则的线性数据结构。***队列模拟了排队现象&#xff0c;即新来的人不断加入队列尾部&#xff0c;而位于队列头部的人逐…

Visual studio+Qt开发环境搭建以及注意事项和打开qt的.pro项目

下载qt-然后安装5.14.2_msvc2017 不知道安装那个就全选5.14.2的父级按钮 https://download.qt.io/archive/qt/5.14/5.14.2/ 安装Visual studio,下载直接下一步就行 配置Visual studio的qt环境 在线安装-重启Visual studio会自动安装 离线安装-关闭Visual studio点击安装 关闭…

a16z:加密行业2024趋势“无缝用户体验”

近日&#xff0c;知名加密投资机构a16z发布了“Big ideas 2024”&#xff0c;列出了加密行业在 2024 年几个具备趋势的“大想法”&#xff0c;其中 Seamless UX&#xff08;无缝用户体验&#xff09;赫然在列。 从最为直观的理解上&#xff0c;Seamless UX 是在强调用户在使用产…

路由器原理

目录 一.路由器 1.路由器的转发原理 2.路由器的工作原理 二.路由表 1.路由表的形成 2.路由表表头含义 直连&#xff1a; 非直连&#xff1a; 静态 静态路由的配置 负载均衡&#xff08;浮动路由&#xff09; 默认路由 动态 三.交换与路由对比 一.路由器 1.路由器…

独立完成软件的功能的测试(4)

独立完成软件的功能的测试&#xff08;4&#xff09; &#xff08;12.14&#xff09;&#xff08;功能测试>头条项目实战&#xff09; 项目总体概述 项目背景和定位&#xff1a;一款汇聚科技咨询&#xff0c;技术文章和问答交流的用户移动终端产品&#xff0c;用户可以通过…

STM32在CTF中的应用和快速解题

题目给的是bin文件&#xff0c;基本上就是需要我们手动修复的固件逆向。 如果给的是hex文件&#xff0c;我们可能需要使用MKD进行动态调试 主要还是以做题为目的 详细的可以去看文档&#xff1a;https://pdf1.alldatasheet.com/datasheet-pdf/view/201596/STMICROELECTRONIC…

微服务学习:Gateway服务网关

一&#xff0c;Gateway服务网关的作用&#xff1a; 路由请求&#xff1a;Gateway服务网关可以根据请求的URL或其他标识符将请求路由到特定的微服务。 负载均衡&#xff1a;Gateway服务网关可以通过负载均衡算法分配请求到多个实例中&#xff0c;从而平衡各个微服务的负载压力。…

一入二出热电阻温度信号隔离变送器

一入二出热电阻温度信号隔离变送器 用于测量铂热电阻Pt10,Pt100,Pt1000,Cu50,Cu100的热电阻传感器的小型仪器设备。广泛应用于工业测量温度系统&#xff0c;是降低成本且有效的测量方式。 型号&#xff1a;JSD TARZ-1002系列 我们来看下有什么特点&#xff1a; ◆小体积&#x…

天猫数据分析平台-天猫销售数据查询软件-11月天猫平台冲锋衣市场销售运营数据分析

随着气温逐渐下降&#xff0c;保暖服饰迎来热销&#xff0c;冲锋衣的需求大增。如今冲锋衣已经不仅仅是户外运动的装备&#xff0c;还成为很多年轻人的日常穿搭和时尚的追求。 新的穿搭趋势也带来了巨大的市场机会。据公开数据显示&#xff0c;中国有冲锋衣生产及经营企业超过8…

竞赛保研 python+opencv+机器学习车牌识别

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器学习的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;3分 该项目较为新颖&#xff0c;适…

什么是纯净IP?如何判断IP地址的纯净度?有哪些干净IP推荐?

您是否想知道什么使代理“干净”或如何确保您的代理不会将您列入网站的黑名单&#xff1f;对于通过代理访问网络的人来说&#xff0c;干净的代理是无缝在线体验的重要组成部分。在这篇文章中&#xff0c;我们将深入研究干净代理的世界&#xff0c;并探讨决定其质量的因素。 一、…

k8s常用命令及示例(三):apply 、edit、delete

k8s常用命令及示例(三)&#xff1a;apply 、edit、delete 1. kubectl apply -f 命令&#xff1a;从yaml文件中创建资源对象。 -f 参数为强制执行。kubectl apply和kubectl create的区别如下&#xff1a;kubectl create 和 kubectl apply 是 Kubernetes 中两个常用的命令&…

加速数据采集:用OkHttp和Kotlin构建Amazon图片爬虫

引言 曾想过轻松获取亚马逊上的商品图片用于项目或研究吗&#xff1f;是否曾面对网络速度慢或被网站反爬虫机制拦截而无法完成数据采集任务&#xff1f;如果是&#xff0c;那么本文将为您介绍如何用OkHttp和Kotlin构建一个高效的Amazon图片爬虫解决方案。 背景介绍 亚马逊&a…

Spring Boot之自定义starter

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