平地起C楼—第十层《详解文件操作》

在这里插入图片描述

🏳‍🌈前言

在这里插入图片描述

对一台计算机来说,最基本的功能即存储数据;一般情况下,数据在计算机中上都是以文件形式存储的。在C语言程序设计中是需要对文件进行操作的。比如:打开文件、读写文件、关闭文件等操作;本章就对文件操作进行详细讲解。

1. 文件概念

文件:存储在外部介质上数据的集合。外部介质比如说磁盘(硬盘)。
在存储文件的时候必须写文件名,通过文件名来访问所保存的文件。一个文件要有唯一的标识符,方便用户查找。文件标识包括3部分:
①文件路径;②文件名;③文件扩展名;【注意的是:文件名中不能有特殊符号,比如说‘/’,因为存在转移字符和文件路径冲突】
然而:文件扩展名有很多,比如:.txt、doc、jpg、c、exe等。

2. 文件分类

根据数据的组织形式,文件可以分为文本文件、二进制文件。

2.1 文本文件

文本文件:又被称为ASCII文件。每一个字节存放一个字符的ACSCII码。比如:整数10000。若用文件形式输出到磁盘上,存储形式如下图:
在这里插入图片描述
从上图可以看出,一个字符占用一个字节,整数10000共占5Byte。

2.2 二进制文件

数据在内存中是以二进制形式存储的,若不加转换地输出到磁盘上去,就是二进制文件。简单说,二进制文件就是存储在内存中的数据的映像,所以叫做映像文件。比如:整数10000。若以二进制文件存储到磁盘中:
在这里插入图片描述
可以看到只需要4个字节,只是存储内容不直观,需要转换一下才可以一眼看出。

2.3 文本文件和二进制文件的对比

(1)文本文件
优点:①文本文件比较直观,便于对字符进行逐个处理。②不需要任何转换。
缺点:①占用的存储空间较多。②读取文件时候花费更多时间。(因为需要转换一次)
(2)二进制文件
优点:①节省空间。②节省时间。
缺点:①存放内容不直观。

总结:若希望加载文件和生成文件的速度较快,并且生成的文件较小,建议使用二进制文件;若希望生成的文件无需经过任何转换就可以看到存放内容,建议使用文本文件。

3、文件指针

在C语言中,文件的所有操作必须依赖文件指来完成。在进行文件操作的时候,必须先将文件和文件指针联系起来。

3.1文件指针定义形式

FILE* <变量名>;

上面的FILE是由系统声明的定义文件指针的结构体,用于保存文件相关的信息,比如:文件名、文件位置、文件大小、文件状态等信息。下面是C语言中FILE结构体定义 :

typedef struct 
{
	short level;//缓冲区满或空的程度
	unsigned flags;//文件状态标识
	char fd;//文件描述符
	unsigned char hold;//若无缓冲区不读取字符。
	short bsize;//缓冲区大小 
	unsigned char* buffer;//数据传送缓冲区位置
	unsigned char* curp;//当前读写位置
	short token;//无效检测
}FLIE;//结构体类型名

每当打开⼀个⽂件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信息,使⽤者不必关⼼细节。

  • 有文件结构体之后,就可以文件指针了,形式如下:
FILE* pf;//文件指针

定义好文件指针后,还未和文件关联起来,此时文件信息区还没有任何文件信息。
文件指针需要通过fopen()函数来关联文件,它用于打开文件。如下:

FILE* pf=fopen("test.txt");//打开文件test。

4. 文件操作

4.1 文件打开\关闭

文件最基本的操作就是文件的打开和关闭。在对文件进行任何读写的前提都是先打开文件,读写完后再关闭文件。

4.1.1 fopen()函数

文件操作之前,第一步先打开文件,函数原型如下:

FILE* fopen(const char* filename,const char* mode);

返回类型为FILE* 表示文件指针类型;filename用于指定文件的绝对路径,即包含路径名和文件的扩展名。
mode表示文件的打开模式。
文件打开模式如下:

打开模式名称作用
“r”/“rb”只读模式打开一个文本文件/二进制文件,只允许读取数据,文件不存在时打开失败,返回NULL。
“w”/“wb”只写模式创建一个文本文件/二进制文件,只允许写入数据,文件已经存在的时候,则覆盖原来文件;不存在时会创建新的文件。
"a”/“ab”追加模式打开一个文本文件/二进制文件,只允许在文件末尾添加数据,文件不存在时,会创建新的文件。
"r+”/“rb+”读取/更新模式打开一个文本文件/二进制文件,允许进行读取和写入操作,文件不存在时打开失败,返回NULL。
“w+/“wb+”写入/更新模式创建一个文本文件/二进制文件。允许进行读取和写入数据,若文件已经存在,则重写文件,没得就创建一个文件。
“a+”/“ab+”追加/更新模式打开一个文本文件/二进制文件,允许进行数据读取和追加操作,文件不存在,则创建新文件。
4.1.2 fclose()函数

打开文件后,读写结束后,需要关闭文件。关闭文件是释放缓冲区和其他资源的过程,不关闭会耗费系统资源。fclose()函数就是用来关闭文件的。声明如下:

int fclose(FILE* pf);//返回值为int,关闭成功返回0,否则返回EOF(-1)。

4.2 文件操作实例

//1、文件操作
#include<stdio.h>
#include<stdlib.h>
int main()
{
    FILE* pf=fopen("hello.txt","w");//打开文件,不存在则创建
    //判断
    if(pf==NULL)
    {
        perror("open file fail");
        exit(0);//退出程序
    }
    //写入一个字符串
    fputs("Hello word!\n",pf);
    //关闭文件
    fclose(pf);
    printf("文件写入成功!\n");
    return 0;
}

结果展示:
在这里插入图片描述

4.3文件写入函数

在程序设计时,经常会对文件进行读写操作。文件的读写操作分为两种形式:①以字符形式进行写入;②以二进制形式进行写入;

4.3.1 fputc()函数——单个字符写入

fputc()函数作用:向文件中写入一个字符,只能单个字符写入。声明如下:

int fputc(int c,FILE* stream);

c表示写入的内容,
stream表示文件指针。
函数返回值为int
写入成功,返回成功写入的字符,否则返回EOF

1、代码演示:

//2、fputc()函数使用,向文件写入一个字符
#include<stdio.h>
#include<stdlib.h>//exit()函数的头文件
int main()
{
    //写入的内容
    char ch[]="I like program!";
    FILE* pf=fopen("hello.txt","w");
    //判断
    if(pf==NULL)
    {
        printf("打开文件失败!\n");
        exit(0);
    }
    //写入
    int i=0;
    while(ch[i]!='\0')
    {
        fputc(ch[i],pf);
        i++;
    }
    //关闭文件、
    fclose(pf);
    return 0;
}

结果展示:
在这里插入图片描述

4.3.2 fputs()函数——字符串写入

fputs()函数的作用:将字符串写入文件中,声明如下:

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

str表示:带写入的字符串的字符指针。
stream表示文件指针。
写入成功函数返回0,否则返回EOF

2、代码演示:

//3、fputs()函数的使用,写入字符串
#include<stdio.h>
#include<stdlib.h>
int main()
{
    char *str[3];//定义字符数组的指针——字符数组指针
    str[0]="I like program!\n";
    str[1]="It is amazing!\n";
    str[2]="It is interesting!\n";
    FILE* pf=fopen("hello.txt","w");
    //判断
    if(pf==NULL)
    {
        printf("文件打开失败!\n");
        exit(0);
    }
    //写入
    for(int i=0;i<3;i++)
    {
        fputs(str[i],pf);
    }
    //关闭
    fclose(pf);
    return 0;
}

结果展示:
在这里插入图片描述

4.3.3 fwrite()函数——二进制写入

fwrite()函数的作用:以二进制的形式写入文件。声明如下:

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

ptr表示:待写入数据的指针;
size表示:写入数据的字节数;
number表示:待写入size字节的数据的个数;
stream表示:文件指针;
返回值为size-t,即无符号整型,写入成功返回写入的数据次数,否则返回0;

3、代码演示:

//4、fwrite()函数的使用,二进制形式写入文件
#include<stdio.h>
#include<stdlib.h>
int main()
{
    char str[26];//存放26英文字符
    FILE* pf=fopen("hello.txt","w");
    if(pf==NULL)
    {
        printf("打开文件失败!\n");
        exit(0);
    }
    for(int i=0;i<26;i++)
    {
        str[i]='a'+i;
    }
    int num=fwrite(str,sizeof(char)*13,2,pf);//第一次写入前13个字母,
    //第二次写入后面13个
    printf("写入次数:%d\n",num);
    fclose(pf);
    return 0;
}

结果展示:
在这里插入图片描述
文件中内容:
在这里插入图片描述

4.3.4 fprintf()函数——格式化写入

fprintf()函数的作用:将数据格式化后写入文件。声明如下:

int fprintf(FILE* stream,const char* format,……);

stream表示:文件指针;
format表示:以什么样的字符串格式输出到文件中;
该函数根据指定的字符串格式将字符串写入到指定文件。
调用成功,返回输出的字符数,否则返回EOF

4、代码演示:

//fprintf()函数的使用,格式化写入
#include<stdio.h>
#include<stdlib.h>
int main()
{
    FILE* pf=fopen("hello.txt","w");
    if(pf==NULL)
    {
        printf("打开失败!\n");
        exit(0);
    }
    //将格式化的字符串输出到文件中
    fprintf(pf,"I am a %s,I am %d years old.","programer",26);
    fclose(pf);
    return 0;
}

结果展示:
在这里插入图片描述

4.4 文件读取函数

在C语言中,除开写入函数外,还有文件读取函数。下面一一介绍文件读取函数:

4.4.1 fgetc()函数——单个字符读取

fgets()函数的作用:读取文件的字符,单个读取。声明如下:

int fgetc(FILE* stream);

stream表示:文件指针。
函数将读取的字符转换为整数返回,读取文件到末尾或读取错误返回EOF

1、代码演示:

//6、fgetc()函数的使用,读取单个字符
#include<stdio.h>
#include<stdlib.h>
int main()
{
    FILE* pf=fopen("hello.txt","r");
    if(pf==NULL)
    {
        printf("打开文件失败!\n");
        exit(0);
    }
    //读取
    char ch=0;
    while((ch=fgetc(pf))!=EOF)
    {
        printf("%c",ch);
    }
    fclose(pf);
    return 0;
}

结果展示:
在这里插入图片描述

4.4.2 fgets()函数——字符串读取

fgets()函数的作用:从文件中读取一行字符串,或则读取指定长度的字符串,声明如下:

char* fgets(char* s,int size,FILE* stream);

s表示:用来存储数据的空间;
size表示:读取的数据大小;
stream表示:读取文件的文件指针;
读取成功返回s,读取错误或则遇到文件末尾,则返回NULL。

fgets()从文件中读取数据时候,最多读取size-1个数据,将读取的数据保存到s指向的字符数组中,读取的字符串会在最后添加一个’\0’。

【fgets()函数读取停止的情况一般是这3种:】
①读取size-1个字符前,遇到'\n',读取结束,末尾添加'\0'
②读取size-1个字符前,遇到EOF,读取结束,末尾添加'\0'
③完成size-1个字符读取,读取结束,末尾添加'\0'

2、代码演示:

//7、fgets()函数的使用,读取字符串
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
    FILE* pf=fopen("hello.txt","r");
    if(pf==NULL)
    {
        printf("打开文件失败!\n");
        exit(0);
    }
    //读取
    char str[50];//文件数据缓冲区
    while(!feof(pf))//判断文件指针是否已经指到文件的末尾。
    {
        fgets(str,sizeof(str),pf);//将文件中的数据复制到文件数据缓冲区str中
        printf("%s",str);
    }
    fclose(pf);
    return 0;
}

结果展示:
在这里插入图片描述

4.4.3 fread()函数——二进制形式读取

fread()函数的作用:以二进制形式读取文件,声明如下:

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

ptr表示:指向要接收读取数据的内存空间的指针;
size表示:读取元素的大小;
number表示:读取元素的个数;
stream表示:文件指针。
fread()函数从一个文件中读取数据,最多读取number个元素,每个元素的大小为size个字节。读取成功,返回读取数据的大小,读取错误返回0

3、代码演示:

//fread()函数——二进制形式读取
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
    FILE* pf=fopen("hello.txt","r");
    if(pf==NULL)
    {
        printf("打开文件失败!\n");
        exit(0);
    }
    char str[30];
    memset(str,0,sizeof(0));//把字符数组初始化为0
    int len=0;
    while(!feof(pf))
    {
        len=fread(str,1,28,pf);
        printf("%s\n",str);
    }
    fclose(pf);
    printf("读取的实际大小:%d\n",len);
    return 0;
}

结果展示:
在这里插入图片描述

4.4.4 fscanf()函数——格式化读取

fscanf()函数的作用:从文件中格式化读取数据,声明如下:

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

format表示:文件中的数据以什么格式输入到程序中。
调用成功,返回输入的参数的个数;否则返回EOF

4、代码演示:

//9、fscanf()函数——格式化读取
#include<stdio.h>
#include<stdlib.h>
int main()
{
    char arr1[100],arr2[100];
    FILE* pf=fopen("hello.txt","r");
    if(pf==NULL)
    {
        perror("fopen");
        exit(0);
    }
    fscanf(pf,"%s %s",arr1,arr2);
    printf("%s\n",arr1);
    printf("%s\n",arr2);
    fclose(pf);
   
    return 0;
}

结果展示:
在这里插入图片描述

5. 文件随机访问函数

文件位置指针:简单说就是文件里面的光标

函数名格式作用
rewind()void rewind(FILE* stream);将文件位置指针指向文件开头
fseek()int fseek(FILE* stream,long offser,int where);将文件位置指针指向指定位置。
ftell()long ftell(FILE* stream);获取文件位置指针的当前位置

在这3个函数中,fseek()中的参数需要说明:
offset:表示参数where移动读/写位置的偏移量。
where:有3个值可以取;
①SEEK_SET: 表示数字0,表示从文件开头进行偏移。
②SEEK_CUR:表示数字1,表示从文件位置指针的当前位置开始偏移。
③SEEK_END:表示数字2,表示从文件末尾开始偏移,此时向前偏移,所以offset是负数。
偏移成功,返回0,失败返回-1。

6. 文件重命名和删除

函数名格式作用
rename()int rename(const char* oldname,const char* newname);对文件重命名
remove()int remove(const char* Filename);删除文件

7.文件检测函数

函数名格式作用
perror()void perror(const char* str);打印错误信息
ferror()int ferror(FILE* stream);检查输入/输出函数进行读/写操作时候是否报错
feof()int feof(FILE* stream);判断文件是否处于文件结束位置
clearerr()void clearerr(FILE* stream);清楚错误标志和文件结束标志
  • 53
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值