• C语言的文件操作


    🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸

    在这里插入图片描述

    今天带来的内容是C语言中的文件操作

    下面要今天要讲的知识内容🥳🥳🥳

    一、🚒前言

    相信大家在学校都会写一个通讯录的项目吧。通讯录可以有三种版本
    1.静态版本,用数组的方式去实现
    2.动态版本,动态开辟内存去实现
    3.文件版本,将联系人的信心储存起来,并且打开的时候可以 调出来直接进行使用

    下面我们就来谈谈第三种方式中的文件操作


    二、🚀关于文件的几个问题

    1.为什么使用文件?
        文件使我们的存储持久化,保存在电脑硬盘当中
    2.什么是文件?
        也就是保存在磁盘上的文件
    3.程序设计中,我们将文件分为哪两种?
        a.程序文件
        程序文件包括源文件,目标文件,可执行程序等等。
        b.数据文件
        文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取文件,或者输出内容的文件.

    三、🚀文件指针

    缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”
    每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(比如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的,该结构体类型是有系统声明的,取名FILE
    在这里插入图片描述
    不同的编译器对FILE的内部实现是不完全相同的,但是大同小异
    每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构体变量,并填充其中的信息,使用者不必关心细节
    我们可以通过一个FILE的指针来维护这个FILE结构的变量,FILE*pf;

    文件是在硬盘上的,文件信息区是在内存上的
    写出来的C语言程序是没有办法直接操作文件的,会借助操作系统

    四、🚀文件的打开和关闭

    文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
    ANSIC规定使用fopen来打开文件,使用fclose来关闭文件

    ⛄fopen与fclose

    在这里插入图片描述
    有这么几种模式
    "r"为了文件向外输入数据,打开一个已经存在的文本文件,文件不存在则出错
    "w"为了向文件输出数据,打开一个文本文件,不存在则建立一个新的文件
    "a"向文本文件尾添加数据,文件不存在则建立一个新文件
    “w+”
    “a+”
    “r+”
    "rb"二进制的读
    "wb"二进制的写
    "ab"二进制的追加

    fopen在打开文件的时候,就会创建和这个文件相关的文件信息区,同时fopen函数返回这个文件信息区的起始地址,所以返回类型是FILE*,是一个结构体指针,遇到error会返回一个空指针

    在这里插入图片描述

    五.🚀文件的顺序读写

    概要

    字符输入函数 fgetc
    字符输出函数 fputc
    文本行输入函数 fgets
    文本输出函数 fputs
    格式化输入函数 fscanf
    格式化输出函数 fprintf
    以上适用于所有输入/输出流
    二进制输入 fread 适用于文件
    二进制输出fwrite 适用于文件

    1.⛄fgetc、fputc

    返回的是读到的字符的ASCLL码值,读取错误或者遇到文件结束会返回一个EOF
    因为读取错误或者遇到文件结束会返回一个EOF,EOF也就是-1,所以用int作返回类型更合适

    在这里插入图片描述

    int main()
    {
    	//打开文件
    	FILE* pf = fopen("test.txt", "w");//写入
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    	//写文件
    	/*fputc('a',pf);
    	fputc('b',pf);
    	fputc('c',pf);
    	fputc('d',pf);
    	fputc('e',pf);
    	fputc('f',pf);*/
    	char ch = 'a';
    	for (char i = ch; i <= 'z'; i++)
    	{
    		fputc(i,pf);
    	}
    	
    	//关闭文件
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    因为读取文件后它的光标是不返回开头位置的,所以一定有一个状态来维护当前文件位置,所以这也能够说明FILE指针的作用

    int main()
    {
    	int ch=fgetc(stdin);//从标准输入流中读取:也就是指的键盘
    	/*printf("%c\n", ch);*/
    	fputc(ch, stdout);//打印到标准输出流:也就是指的屏幕
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    关于流
    在这里插入图片描述

    2.⛄fgets、fputs

    在这里插入图片描述

     
    int main()
    {
    	FILE* pf = fopen("test.txt", "r");
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    
    
    	写一行,读一行
    	char  str[256] = { 0 };
    	//fgets(str, 255, pf);
    	//puts(str);
    	while (fgets(str, 256, pf) != NULL)
    	{
    		puts(str);
    	}
    
    
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    换行也读进去了的,因为字符串默认结尾就有一个换行,写的时候又多加了一个换行,等于有两个换行,fgets的参数n就算写多了也只能读n-1个,会留一个放\0,有\0才算是字符串

    3.⛄fprintf、fscanf

    fscanf - 针对所有输入流的格式化输入函数,
    fprinf - 针对所有输出流的格式化输出函数

    在这里插入图片描述
    在这里插入图片描述

    int main()
    {
    	struct S s = { 0 };
    
    	FILE* pf = fopen("test.txt", "r");
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    
    	//读文件
    	fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d));
    	printf("%s %d %lf",s.name,s.age,s.d);
    
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    struct S
    {
    	char name[20];
    	int age;
    	double d;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4.⛄sprintf、sscanf

    sscanf - 把一个字符串转换成格式化的数据
    sprintf - 把一个格式化的数据转换成字符串

    在这里插入图片描述
    在这里插入图片描述

    
    int main()
    {
    	char buf[256] = { 0 };
    
    	struct S s = { "zhangsan",20,95.5 };
    	struct S tmp = { 0 };
    	sprintf(buf,"%s %d %lf",s.name,s.age,s.d);
    	puts(buf);
    	//从buf字符串中,提取结构体数据
    	sscanf(buf,"%s %d %lf",tmp.name,&tmp.age,&tmp.d);
    	printf("%s %d %lf",tmp.name,tmp.age,tmp.d);
    
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    5.⛄fread,fwrite

    二进制写wb
    二进制读rb

    在这里插入图片描述

    struct S
    {
    	char name[20];
    	int age;
    	double d;
    };
    int main()
    {
    	struct S s = { "zhangsan",20,95.5 };
    	struct S tmp = { 0 };
    	FILE*pf=fopen("text3.txt","wb");
    
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    	//二进制的方式写
    	fwrite(&s,sizeof(struct S),1,pf);
    	
    
    
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    
    int main()
    {
    	struct S tmp = { 0 };
    	FILE* pf = fopen("text3.txt", "rb");
    
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    	//二进制的方式读
    	fread(&tmp, sizeof(struct S), 1, pf);
    	printf("%s %d %lf", tmp.name, tmp.age, tmp.d);
    
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    6.⛄文件的随机读写fseek

    fseek是根据文件指针的位置和偏移量来定位文件指针的。
    int fseek(FILE*stream,long int offset,int origin);
    offset是偏移量,origin是起始

    在这里插入图片描述
    origin有三个选项
    SEEK_CUR文件指针当前的位置
    SEEK_END文件末尾的位置
    SEEK_SET文件开始的位置

    int main()
    {
    	FILE*pf=fopen("test.txt", "r");
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    
    	//随机读
    	int ch = fgetc(pf);
    	printf("%c ",ch);
    	fseek(pf, 3, SEEK_CUR);
    	ch = fgetc(pf);
    	printf("%c ",ch);
    
    
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    
    
    
    int main()
    {
    	FILE* pf = fopen("test.txt", "w");
    	if (pf == NULL)
    	{
    		perror("fopen");
    		return 1;
    	}
    
    	//随机写
    	fputc('a',pf );
    	fputc('b',pf );
    	fputc('c',pf );
    	fputc('d',pf );
    
    	fseek(pf,-3,SEEK_CUR);
    	fputc('w', pf);
    
    	long pos = ftell(pf);
    	printf("%ld\n",pos);
    
    	rewind(pf);
    	pos = ftell(pf);
    	printf("%ld\n",pos);
    
    
    	fclose(pf);
    	pf = NULL;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    7.⛄ftell、rewind

    fell返回的文件指针相对于起始位置的偏移量在这里插入图片描述

    rewind让文件指针的位置回到文件的起始位置
    在这里插入图片描述

    六.🚀文件文本和二进制文本

    根据数据的组织形式,数据文件被称为文本文件或者二进制文件
    数据在内存中是以二进制的形式储存,如果不加转换的输出到外存,就是二进制文件
    如果要求在外存上以ASCLL码的形式存储,则需要在存储前转换,以ASCLL字符的形式存储的文件就是文本文件

    、🚀

           创作不易,提前感谢各位老铁的一键三连,我会和大家一起进步,拿下offer。如果觉得这篇文章有什么帮助的话,👈👇👉点点点。谢谢大家的支持,你的支持就是我前进的动力!!!
    在这里插入图片描述

  • 相关阅读:
    k8s--基础--16--Service--理论
    GO语言-反射reflect
    基于JAVA抑郁症患者博客交流平台计算机毕业设计源码+系统+数据库+lw文档+部署
    bp网络和卷积神经网络,bp神经网络
    U_BOOT_DRIVER简析
    数据结构-链表(java)
    【最佳实践】瀚高数据库企业版v6.0.2在Centos7.8安装过程
    浅谈关于数据仓库的理解,聊聊数据仓库到底是什么?
    【校招VIP】java开源框架之spark
    Linux无文件木马程序渗透测试复现
  • 原文地址:https://blog.csdn.net/zhu_pi_xx/article/details/126127142