【C】940/bit2-6文件操作

【参考课程:B站  BV1Vm4y1r7jY】P155-160

1.为什么使用文件

使用文件可以将数据直接存放在电脑的硬盘上,做到了数据的持久化


2.什么是文件

磁盘上的文件是文件
但是在程序设计中,我们一般谈的文件有两种(从文件的功能角度分类):程序文件、数据文件

2.1程序文件

包括源程序文件(.c)

目标文件(Windows环境后缀为.obj)

可执行程序(Windows环境后缀为.exe)

2.2数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件

写文件:内存→文件
读文件:文件→内存

2.3文件名

一个文件要有一个唯一的文件标识,以便于用户识别和引用
文件名包含3部分:文件路径文件名主干文件后缀       E.g. c:\code\test.txt
为了方便起见,文件标识常被称为文件名


3.文件的打开和关闭

3.1文件指针

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针

文件指针:在C语言中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息
        →这些信息保存在一个结构体变量
                                           *该结构体类型是有系统声明的,取名为FILE.  //声明在<stdio.h>中

#ifndef _FILE_DEFINED
    #define _FILE_DEFINED
    typedef struct _iobuf
    {
        void* _Placeholder;
    } FILE;
#endif

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息。(使用者不必关心细节)
一般通过一个FILE指针来维护这个FILE结构的变量

创建一个FILE*的指针变量:

#include<stdio.h>
FILE* pf; //文件指针变量

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

3.2文件的打开和关闭

打开fopen( )

w 写文件会将文件内容全部清空后再写内容

a 不会覆盖原文件内容

关闭fclose( )

#include<stdio.h>
#include<string.h> //包含strerror()
int main()
{
	FILE* pf;
	//打开文件
	pf = fopen("test.txt", "r"); //r-读文件需要文件存在
	if (pf == NULL) //判断文件是否存在 //文件不存在指针会指向空指针
	{
		printf("%s\n", strerror(errno));//打印未能成功打开文件的原因
		return 1;
	}
	
	//关闭文件
	fclose(pf);//记得要关闭文件,∵程序可打开的文件数量有限;不关闭文件可能会丢失文件数据
	pf = NULL;//重置文件指针
	return 0;
}

文件不存在打印:

在该程序文件路径下存在test.txt时文件会读取成功

相对路径/绝对路径

//相对路径
pf = fopen("test.txt", "r"); //打开当前目录下的test.txt文件

//绝对路径
pf = fopen("C:\\Users\\achir\\Desktop\\test.txt", "r"); //打开指定路径下的test.txt文件

4.文件的顺序读写

fputc( )

#include<stdio.h>
#include<string.h>
int main()
{
	//打开文件
	FILE* pf;
	pf = fopen("test.txt", "w"); 
	if (pf == NULL) //判断文件是否存在 
	{
		perror("fopen"); //等价于printf("%s\n", strerror(errno))
		return 1;
	}
///***写文件***///
	fputc('a', pf);	//写入一个字符

	//关闭文件
	fclose(pf);
	//pf = NULL;//重置文件指针
	return 0;
}

        perror("fopen"); 打印:

fgetc( )
#include<stdio.h>
#include<string.h>
int main()
{
	//打开文件
	FILE* pf;
	pf = fopen("test.txt", "r"); 
	if (pf == NULL) //判断文件是否存在 
	{
		perror("fopen");
		return 1;
	}

///***读文件***///
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF) //fgetc按顺序一个一个向后读取字符,能换行读
	{								//读取完毕不能再读时fgetc()返回EOF
		printf("%c", ch);			//此循环可将文件字符按顺序全部打印
	}

	//关闭文件
	fclose(pf);
	//pf = NULL;//重置文件指针
	return 0;
}
fputs( )

#include<stdio.h>
#include<string.h>
int main()
{
	FILE* pf;                    //w-会覆盖原内容(在打开文件时即将内容清空)
	pf = fopen("test.txt", "a"); //a-在原内容后追加
	if (pf == NULL) 
	{
		perror("fopen");
		return 1;
	}

///***写文件***///
	fputs("hello", pf); //写一行内容

	//关闭文件
	fclose(pf);
	//pf = NULL;//重置文件指针
	return 0;
}
fgets( )

#include<stdio.h>
#include<string.h>
int main()
{
	FILE* pf;
	pf = fopen("test.txt", "r"); 
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

///***读文件***///
	char ch[20]; //创建字符数组接受读取内容
	fgets(ch, 9, pf); 
	//从【pf】指向的文件中读取【9】个字符,将读到的内容存在数组【ch】中
	printf("%s\n", ch);//可将ch打印出来观察

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}
  • 读取的字符个数中包括\0,真正有效读取字符-1
       即:用fgets(ch, 2, pf)读abcd,则得到ch[20]={'a','\0'}
  • fgets( )只能读同一行上的字符
fprintf( )

格式化的向文件写入信息

#include<stdio.h>
#include<string.h>
struct S
{
	char name[10];
	int a;
	float f;
};
int main()
{
	struct S s1 = { "ergo",4,6.6 };

	FILE* pf;
	pf = fopen("test.txt", "w");
	
	fprintf(pf,"%s %d %f",s1.name,s1.a,s1.f); 
    //格式化的把s1的内容写进pf指向的文件test.txt中

	fclose(pf);
	pf = NULL;
	return 0;
}
fscanf( )

格式化的从文件读取信息

#include<stdio.h>
#include<string.h>
struct S
{
	char name[10];
	int a;
	float f;
}s1,s2;
int main()
{
	FILE* pf;
	pf = fopen("test.txt","r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fscanf(pf, "%s %d %f", &(s1.name), &(s1.a), &(s1.f));
	fscanf(pf, "%s %d %f", &(s2.name), &(s2.a), &(s2.f));
    //一行一行按顺序的格式化读取文件内容
	printf("%s %d %f\n", s1.name, s1.a, s1.f);
	printf("%s %d %f\n", s2.name, s2.a, s2.f);


	fclose(pf);
	pf = NULL;
	return 0;
}
fwrite( )

fread( )

*文件的顺序读写默认从文件开头开始一一读取 

5.文件的随机读写

fseek( )

根据文件指针的起始位置origin偏移量offset来定位文件指针

#include<stdio.h>
#include<string.h>
int main()
{
	FILE* pf;
	pf = fopen("test.txt", "r");	//test.txt内容:
	if (pf == NULL)					//abcdefg
	{								
		perror("fopen");
		return 1;
	}
	//读文件
	//定位文件指针 [
	fseek(pf, 2, SEEK_SET);//从文档头右偏移2位开始读 //位数从0开始 
	int ch = fgetc(pf);			//[abcdefg → ab[cdefg //读完后变成 abc[defg
	printf("%c\n", ch); //c

	fseek(pf, 1, SEEK_CUR);//从当前指针位置右偏1位开始读 
	ch = fgetc(pf);				//abc[defg → abcd[efg
	printf("%c\n", ch); //e

	fseek(pf, -1, SEEK_END);//从末尾左偏1位开始读 
	ch = fgetc(pf);				//abcdefg[ → abcdef[g
	printf("%c\n", ch); //g

	return 0;
}
ftell( )

返回文件指针相对起始位置的偏移量

	fseek(pf, 2, SEEK_SET);
	printf("%d\n", ftell(pf)); //2
                                          //test.txt内容:
	int ch = fgetc(pf);	                  //abcdefg
	printf("%d\n", ftell(pf)); //3

	fseek(pf, 1, SEEK_CUR);
	printf("%d\n", ftell(pf)); //4

	fseek(pf, -1, SEEK_END);
	printf("%d\n", ftell(pf)); //6
rewind( )

让文件指针回到起始位置

fseek(pf, 2, SEEK_SET);
printf("%d\n", ftell(pf)); //2

rewind(pf);
printf("%d\n", ftell(pf)); //0

6.文本文件和二进制文件

7.文件读取结束的判定

feof( )

用于判定文件读取结束的原因是什么(是读取失败还是遇到文件末尾而读取结束),
不能用来判断文件是否结束!



//返回非零:读取成功结束
//返回0:读取失败

如何判断文件读取是否结束

  1. 文本文件读取是否结束,判断的返回值是否为EOF(fgetc),或NULL(fgets)
  2. 二进制文件的读取结束,判断返回值是否小于实际要读的个数

8.文件缓冲区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值