首页 > 其他分享 >C语言学习笔记(十)文件操作

C语言学习笔记(十)文件操作

时间:2023-08-12 17:44:33浏览次数:39  
标签:文件 return 笔记 C语言 pf FILE printf NULL

十、文件操作

  • 程序文件

  • 数据文件

本章学习的是数据文件

文件名

包含三部分:

文件路径 + 文件名主干 + 文件后缀

c:\code\test.php

文件类型

  • 文本文件:肉眼就能看懂
  • 二进制文件:数据在内存中以二进制的形式存储,若不加转换就输出到外存,就是二进制文件

字符一律以ASCII码形式存储

数值可以用ASCII形式存储,也可以使用二进制形式存储

如 整数 10000;若以ASCII码形式输出,占5个字节(每个字符一个字节 ’1‘ ’0‘ ’0‘ ’0‘ ’0‘ );

​ 若以二进制形式输出,占4个字节(00000000 00000000 00100111 00010000)

文件缓冲区

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

输出缓冲区

程序缓冲区 磁盘

输入缓冲区

文件指针

​ 每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的,该结构体类型是有系统声明的,取名FILE

FILE f;

一般通过FILE的指针来维护这个FILE结构的变量

创建FILE*的指针变量

FILE* pf;

定义pf是一个指向FILE类型数据的指针变量,可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件

文件的打开和关闭

在读写文件之前要先打开文件

在使用结束之后应该关闭文件

编写程序在打开文件的同时,会返回一个FILE* 的指针变量指向该文件,也相当于建立了指针和文件的关系

用fopen函数来打开文件,fclose来关闭文件

打开方式

//打开文件test.php
FILE* pf = fopen("test.php","r");//以只读模式打开,且test.php就在当前.c文件的路径下
//相对路径
FILE* pf = fopen("../../test.php","r");// ..表示上一级路径,.表示当前路径,注意后面使用单斜杠/
//绝对路径:
FILE* pf = fopen("C:\\code\\test.php","r");//打开绝对路径下的文件,注意有两个斜杠,避免转义

若打开失败,会给 pf 返回一个空指针

#include<errno.h>
if (pf == NULL)//pf指针为空,打开失败
{
	printf("%s",strerror(errno));//打印错误信息
    return 0;
}
//打开成功后关闭文件
fclose(pf);
pf = NULL;//将pf指针置空

注意 当读写的文件不存在时,是否会创建一个新文件

“w”模式下,不管文件是否存在,都会新建一个新的文件把原来的覆盖掉

文件的顺序读写

写入

fputc():一次只能写入一个字符,如果不小心写成字符串,则会逐字覆盖,最后的结果是仅剩最后一个字符

注意:读取一次,文件指针就向后偏移一位

#include<errno.h>
#include<stdio.h>
int main()
{
	FILE* pfWrite = fopen("test.txt","w");//不要忘记等号
	if (pfWrite == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	//写文件
	fputc('a',pfWrite);//fputc()一次只能写入一个字符,如果不小心写成字符串,则会逐字覆盖,最后的结果是仅剩最后一个字符
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
	return 0;
}

fputs():一次可以输入一行字符串

#include<errno.h>
#include<stdio.h>
int main()
{
	FILE* pfWrite = fopen("test.txt","w");//不要忘记等号
	if (pfWrite == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	//写文件
	fputs('hello',pfWrite);
    fputs('hello',pfWrite);//注意:如果没有写入换行符,则默认两行是首尾拼接的
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
	return 0;
}
fwrite(&s,sizeof(struct S),1,pf);//将变量s中的内容写到pf指向的文件中,每个元素的字节大小是struct S的大小,元素的个数为1

读取

fgetc():一次只读取一个字符

#include<errno.h>
#include<stdio.h>
int main()
{
	FILE* pfRead = fopen("test.txt","r");
	if (pfRead == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	//读文件
	printf("%c ",fgetc(pfRead));
	//关闭文件
	fclose(pfRead);
	pfRead = NULL;
	return 0;
}

fgets():一次读取一行字符

#include<errno.h>
#include<stdio.h>
int main()
{
	char buf[1024] = {0};
	FILE* pfRead = fopen("test.txt","r");
	if (pfRead == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	//读文件
	printf("%s",fgetc(buf,1024,pfRead));//将读取到的内容存到buf中,一次最多读取1024个字节 
	//关闭文件
	fclose(pfRead);
	pfRead = NULL;
	return 0;
}
/*得到的结果为:
bit

以上内容之所以有两行,是因为buf自带一个换行符,即buf存储了所要读取的文件中末尾本身自带的换行符*/

注意:输出函数puts()不管原文件是否有换行,都会自动换行

二进制形式读文件:fread()

fread(&tmp,sizeof(struct S),1,pf);//将pf所指向文件中的内容读取出来,存到tmp中

标准输入/输出流

char buf[1024] = {0};
fgets(buf,1024,stdin);//从标准输入流读取
fputs(buf,stdout);//从标准输出流输出
//以上两行等价于
//gets(buf);
//puts(buf);

若要输入/输出处了字符串以外的其他格式的信息

fprintf():格式化输出数据,并将结果写入文件

struct S
{
	int n;
	float score;
	char arr[10];
};
int main()
{
	struct S s = {100,3.14,"abc"};
	FILE* pf = fopen("text.txt","w");
	if (pf == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
    //格式化输出
	fprintf(pf,"%d %f %s",s.n,s.score,s.arr);//将输出的数据打印在pf指向的文件中
    
	fclose(pf);
	pf = NULL;
	return 0;
}

fscanf():格式化输入数据,即将文件读取到的信息放到某个变量里

struct S
{
	int n;
	float score;
	char arr[10];
};
int main()
{
	struct S s = {0};
	FILE* pf = fopen("text.txt","r");
	if (pf == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
    //格式化输入
	fscanf(pf,"%d %f %s",&(s.n),&(s.score),s.arr)// s.arr不需要使用取地址符号
	fclose(pf);
	pf = NULL;
	return 0;
}

  • scanf() 和 printf() 其实就是标准输入流 / 标准输出流的 fscanf() 和 fprintf() ,即后面这组针对的是所有输入流 / 输出流

  • sscanf() 和 sprintf():从字符串中格式化输入 / 输出,即可以将文件中的字符串转换为原有的类型并存储在变量中,也可以将变量中其他类型转化为字符串存储在文件中

文件的随机读写

fseek()

根据文件指针的位置和偏移量来定位文件指针

int main()
{
	FILE* pf = fopen("text.txt","r");
	if (pf == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
    //1.定位文件指针
    fseek(pf,2,SEEK_CUR);//从文件指针当前位置开始(默认是起始位置),向后(右)偏移2个字节
    //2.读取文件
    int ch = fgetc(pf);
    printf("%c ",ch);
	fclose(pf);
	pf = NULL;
	return 0;
}

注意:如果是向前(左)偏移,文件的末尾位置应该是最后一位的后面

​ 如:abcdef ,末尾位置应是 f 后面一位,如果要移动到e,则偏移量应为-2

ftell()

计算当前文件指针相比于初始位置的偏移量

int main()
{
	FILE* pf = fopen("text.txt","r");
	if (pf == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
    fseek(pf,2,SEEK_CUR);
	int pos = ftell(pf);
    printf("%d\n",pos);
	fclose(pf);
	pf = NULL;
	return 0;
}

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

int main()
{
	FILE* pf = fopen("text.txt","r");
	if (pf == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
  	fgetc(pf);//读完以后文件指针向后偏移一位
    rewind(pf);//使pf回到起始位置
	int pos = ftell(pf);
    printf("%d\n",pos);
	fclose(pf);
	pf = NULL;
	return 0;
}

文件结束判定

feof

  • 不是用来判断文件读取是否结束的
  • 是当文件读取已经结束时,用来判断是读取失败,还是遇到文件尾(EOF)结束,即是用来判断文件读取结束的原因

EOF(-1)

文件结束标志

文本文件读取是否结束

判断返回值是否为EOF(fgetc()),或者NULL(fgets())

二进制文件读取是否结束

判断返回值是否小于实际要读取的个数

案例

int main()
{
	FILE* pf = fopen("text.txt","r");
	if (pf == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
    }
    int ch = 0;
    while ((ch=fget(pf)) != EOF)
    {
        putc(ch);
    }
    if(ferror(pf))//遇到错误时,ferror返回一个非零值
    {
        printf("error!\n")
    }
    else if(feof(pf))//feof函数如果是遇到EOF结束的,返回非零值
    {
        printf("end of this file!");
    }
	fclose(pf);
	pf = NULL;
	return 0;
}

标签:文件,return,笔记,C语言,pf,FILE,printf,NULL
From: https://www.cnblogs.com/arongsec/p/17625153.html

相关文章

  • 文件映射缺页中断和匿名页面缺页中断的区别
    文件映射缺页中断和匿名页面缺页中断主要区别在于缺页时的处理方式和触发原因。对于文件映射缺页中断,当程序需要访问文件映射的某个页面但该页面尚未调入内存时,就会触发文件映射缺页中断。这时,操作系统会根据文件映射的约定从磁盘加载相应的文件内容到内存中,然后更新页表,使得程序......
  • 【做题笔记】网络流24题
    Part1.飞行员配对方案问题Problem有两个集合\(A\),\(B\)。给定正整数\(n\),\(m\)。\(A=\{x|1\leqx\leqm\}\),\(B=\{y|m+1\leqy\leqn\}\)。现在要将\(A\)与\(B\)集合的元素一一配对,有若干个配对关系,形如“\(u\),\(v\)可凑一对”。求有多少个元素能配成一对,并求......
  • 正则表达式学习笔记
    .:任意一个字符\d:代表一个数字,等价于[0-9]\D:代表一个非数字,等价于[^\d]或者[^0-9]\s:代表一个空白字符,诸如Space,\n,\r,Tab\S:代表一个非空白字符\w:代表一个单词字符,诸如a,9,_,蛙\W:代表一个非单词字符*:量词,左侧字符串出现任意次(包括\(0\)次)?:量词,左侧字符出现\(\le1\)次+:......
  • exe压缩文件解压后自动运行某一文件,如vbs、cmd、bat
    支持sfx自解压功能的压缩软件一般可以实现标题所示需求,推荐Bandizip(标准版即可),下载安装就是标准版:http://www.bandisoft.com/bandizip/以解压MySoft.exe后自动执行pre_install.vbs为例:1、全选下图文件后,鼠标右键——添加到压缩文件(Bandzip) 2、自解压设置,填写完毕后点击“开......
  • 《Rust编程之道》学习笔记一
    《Rust编程之道》学习笔记一序Rust语言的主要特点系统级语言无GC基于LLVM内存安全强类型+静态类型混合编程范式零成本抽象线程安全程序员的快乐何谓快乐?真正的快乐不仅仅是写代码时的“酸爽”,更应该是代码部署到生产环境之后的“安稳”。程序的三大定律程序必须......
  • 硬件管理平台-硬件网关-插件模块-配置文件
    硬件管理平台-硬件网关-插件模块-配置文件上一篇仅仅将反射的基础模块进行了添加,不过还有很重要的一个配置文件还未进行添加,本文将讲述ini配置文件的添加方式何谓配置文件例如在HardwareGatewayService项目中读取App.config文件或log4net读取config.xml文件相同,本项目也需要添......
  • python复习笔记
    文件操作w=open("c://....","r"或"w"或"a",encoding='utf-8')#字符串后跟b表示二进制文件w.readlines()#读出所有行存入listw.readline()#读出一行,若读完了返回""w.read()#读出所有字符构成字符串w.write("abab")#写入w.close()#关闭impo......
  • 「学习笔记」线段树优化建图
    在建图连边的过程中,我们时常会碰到这种题目,一个点向一段连续的区间中的点连边或者一个连续的区间向一个点连边,如果我们真的一条一条连过去,那一旦点的数量多了复杂度就爆炸了,这里就需要用线段树的区间性质来优化我们的建图了。那棵线段树大概长这个样子。到时候加边的时候是这个......
  • shell 判断文件新旧
    一、-nt判断file1是否比file2新["/data/file1"-nt"/data/file2"]二、-ot判断file1是否比file2旧["/data/file1"-ot"/data/file2"]参考:https://www.imooc.com/article/325970......
  • c语言精通学习「1」: 内存
    1.为什么需要内存(1)计算机为什么需要编程?为什么要写新的程序?计算机编程主要注重两点,结果和过程。比如下面的代码看重的是结果intadd(inta,intb)){returna+b;}下面的代码看重的是过程voidadd(inta,intb){printf("%d",a+b);}而下面的代码既......