C语言文件操作函数总结——超详细

版权声明


本文原创作者:谷哥的小弟
作者博客地址:http://blog.csdn.net/lfdfhl


文件与流


在C语言中有三种标准流:

stdin(standard input stream)标准输入流。在大多数环境中为从键盘输入;scanf( )和getchar( )等函数会从该流中读取字符
stdout(standard output stream)标准输出流。在大多数环境中为输出至显示器界面。printf( )、puts( )、putchar( )等函数会向该流中写入字符。
stderr(standard error stream)标准错误流。在大多数环境中为输出至显示器界面。
在C语言中用FILE表示文件类型并提供相应的操作。FILE定义在<stdio.h>头文件中,其具体实现方法因编译器而异,一般以结构体的形式实现。表示标准流的stdin、stdout、stderr都是指向FILE的指针。

文件常见操作


接下来介绍常见的文件操作。

1、打开文件
利用fopen( )打开文件,函数如下:

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


第一个参数:该参数为字符串类型,表示要打开的文件的名称
第二个参数:该参数为字符串类型,表示打开模式(只读、只写、更新、追加)

fopen( )函数会为要打开的文件创建流并返回一个指向文件对象的FILE*型指针。

2、关闭文件
利用fclose( )打开文件,函数如下:

int fclose( FILE *stream );


输入参数:要关闭的文件的指针
返回值:成功关闭返回0,否则返回EOF

练习:文件的打开与关闭

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp=fopen("D:\\test.txt","r");
    if(fp==NULL){
        puts("文件打开失败");
    }else{
        puts("成功打开文件");
    }
    int result=fclose(fp);
    if(result==0){
        puts("成功关闭文件");
    }else{
        puts("文件关闭失败");
    }
    return 0;
}


结果如下:

成功打开文件
成功关闭文件
3、从文件中读取数据
利用fscanf( )从文件中读取数据,函数如下:

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


与scanf( )函数比起来,fscanf( )函数多了一个输入参数即FILE *stream;它表示从哪个文件读取数据。除此以外,它与scanf( )函数完全相同。例如,要从fp中读取十进制整数值并保存是x,代码如下:

fscanf(fp,"%d",&x);


练习:从文件读取学生的成绩并计算各科平均成绩

在D盘根目录下准备成绩文件score.txt

内容如下:

小明 70 84
小王 80 90
小坤 90 90



代码如下:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int number=0;
    char name[20];
    int chinese;
    int math;
    int chinese_sum=0;
    int math_sum=0;
    FILE *fp=fopen("D:\\score.txt","r");
    if(fp!=NULL){
        puts("开始读取数据");
        while(fscanf(fp,"%s%d%d",name,&chinese,&math)==3){
            printf("%s %d %d\n",name,chinese,math);
            number++;
            chinese_sum=chinese_sum+chinese;
            math_sum=math_sum+math;
        }
        puts("-------------");
        printf("平均 %d %d\n",chinese_sum/number,math_sum/number);
    }else{
        puts("文件打开失败");
    }
    int result=fclose(fp);
    if(result==0){
        puts("成功关闭文件");
    }else{
        puts("文件关闭失败");
    }
    return 0;
}


核心代码就一行:

while(fscanf(fp,"%s%d%d",name,&chinese,&math)==3){ }


在此,利用fscanf( )函数读取score.txt中的每一行数据并将学生名字存入变量name,语文成绩存入chinese,数学成绩存入math;fscanf( )函数的返回值为读取到的数据个数。其余的代码不再解释,也可以参照之前关于scanf( )函数的介绍。

结果如下:

开始读取数据
小明 70 84
小王 80 90
小坤 90 90
-------------
平均 80 88
成功关闭文件


4、向文件中写入数据
利用fprintf( )向文件中写入数据,函数如下:

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


fprintf( )函数的使用也很简单,与printf( )函数比起来它多了一个输入参数即FILE *stream;它表示向哪个文件写入数据。除此以外,它与printf( )函数完全相同。例如,要向fp中写入十进制整数值,代码如下:

fprint(fp,"%d",x);


练习:向文件中写入当前时间

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    FILE *fp;
    time_t currentTime = time(NULL);
    struct tm *timeStruct = localtime(&currentTime);
    if ((fp = fopen("D:\\time.txt", "w"))!= NULL){
        puts("将当前日期和时间保存至文件");
        int year=timeStruct->tm_year + 1900;
        int month=timeStruct->tm_mon + 1;
        int day=timeStruct->tm_mday;
        int hour=timeStruct->tm_hour;
        int minute=timeStruct->tm_min;
        int second=timeStruct->tm_sec;
        fprintf(fp,"%d %d %d %d %d %d\n",year,month,day,hour,minute,second);
        fclose(fp);
    }
    return 0;
}


要点概述:

include包含了与时间相关的头文件<time.h>
利用time( )函数得到系统的日历时间(Calendar Time)
利用localtime( )得到本地时间;该方法的返回值是struct tm类型的指针
从timeStruct中分别获取年月日时分秒
利用fprintf( )将年月日时分秒保存至文件
5、scanf( )、fscanf( )、printf( )、fprintf( )小结
在本文开头,我们提到:标准流的stdin、stdout、stderr都是指向FILE的指针。也就是说:这三者都可以直接传递给fscanf( )、fprintf( )函数的第一个参数。因此可知,以下两组代码的功能是相同的。

scanf("%d",&x);
fscanf(stdin,"%d",&x);
printf("%d",x);
fprintf(stdout,"%d",x);


也就是说:
scanf( )是输入源被限定为标准输入流的fscanf( )
printf( )是输出目标被限定为标准输出流的fprintf( )

6、fgetc( )和fputc( )
之前我们利用putchar( )和getchar( )将键盘输入的文字显示到控制台

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int ch;
    while((ch=getchar())!=EOF){
        putchar(ch);
    }
    return 0;
}


在该示例中是从键盘读入数据,输出到控制台。

在此,介绍两个非常类似的函数。
首先来看fgetc( ):

int fgetc( FILE *stream );


该函数用于从文件中读取一个字符并将其转为int型作为函数的返回值。
接着来看fputc( ):

int fputc( int ch, FILE *stream );


该函数用于向文件中写入一个字符。

练习:将文件内容显示至控制台

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int ch;
    FILE *fp;
    char fileName[FILENAME_MAX];
    printf("请输入文件路径:");
    scanf("%s",fileName);
    if((fp=fopen(fileName,"r"))==NULL){
        puts("文件打开失败");
    }else{
        while((ch=fgetc(fp))!=EOF){
            putchar(ch);
        }
        fclose(fp);
    }
    return 0;
}


核心代码:

利用fgetc( )从文件中读取数据,利用putchar( )将数据显示至控制台

结果如下:

请输入文件路径:d:\\score.txt
小明 70 84
小王 80 90
小坤 90 90


练习:文件的复制

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int ch;
    FILE *sfp;
    FILE *dfp;
    char sName[FILENAME_MAX];
    char dName[FILENAME_MAX];
    printf("请输入源文件路径:");
    scanf("%s",sName);
    printf("请输入目标文件路径:");
    scanf("%s",dName);
    if((sfp=fopen(sName,"r"))==NULL){
        puts("源文件打开失败");
    }else{
        if((dfp=fopen(dName,"w"))==NULL){
             puts("目标文件打开失败");
        }else{
            while((ch=fgetc(sfp))!=EOF){
                fputc(ch,dfp);
            }
            fclose(dfp);
            fclose(sfp);
        }
    }
    return 0;
}


核心代码:

利用fgetc( )从源文件sName中读取数据,利用fputc( )将数据写至目标文件dName。假若dName不存在,则会先创建该文件再进行文件的拷贝;这点和Java中的FileOutputStream是非常类似的。

结果如下:

请输入源文件路径:d:\\score.txt
请输入目标文件路径:d:\\copy.txt


7、fgets( )和fputs( )
与fgetc( )和fputc( )类似,可采用fgets( )和fputs( )从文件中读出或者写入字符串。

先来看fputs( ):

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


将str指向的字符串写入stream指向的文件流,成功返回非负数;反之EOF。请注意:该函数输入完成后不会增加额外的特殊字符(如换行符等)

示例如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp = fopen("D:\\test.txt", "w");
    fputs("hello c programming\n", fp);
    fputs("hello c++ programming\n", fp);
    fclose(fp);
    puts("已将字符串写入文件");
    return 0;
}


结果如下:

已将字符串写入文件


再来看fgets( ):

char *fgets( char *str, int count, FILE *stream );


该函数从文件指针stream指向的文件内读取字符串并保存到指针str所指向的内存空间中,直至已读size-1个字符或出现换行符或文件末尾时为止;当读取错误或者读到文件末尾EOF返回NULL。请注意:该函数会读取最后的换行符’\n’

示例如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char str[300];
    FILE *fp= fopen("D:\\test.txt", "r");
    //读取第一行的内容
    char *strLine1=fgets(str, 200, fp);
    printf("%s",strLine1);
    //读取第二行的内容
    char *strLine2=fgets(str, 200, fp);
    printf("%s",strLine2);
    fclose(fp);
    return 0;
}


结果如下:

hello c programming
hello c++ programming


刚才我们事先知道D:\test.txt文件中有两行文字,所以连续两次调用fgets( )读取数据。但是,很多时候我们事先是不可能知道的文件的内容;所以,代码需要优化:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char str[300];
    FILE *fp= fopen("D:\\test.txt", "r");
    char *stringLine;
    while((stringLine=fgets(str, 200, fp))!=NULL){
        printf("%s",stringLine);
    }
    fclose(fp);
    return 0;
}


8、fread( )和fwrite( )
虽然可使用函数 fprintf ( )和 fscanf( ) 从磁盘文件中读写任何类型的文件,但是效率并不高。所以,我们可采用fread( )和fwrite( )按照二进制的形式对文件进行读写操作。

原型如下:

size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );


两个函数输入参数的个数和类型一致,概述如下:

第一个参数:指向读写数据首地址的指针。
第二个参数:要操作的单个数据的大小。例如,int型数据的大小就是sizeof(int)
第三个参数:数据个数
第四个参数:文件指针
练习:利用fread( )和fwrite( )读写基本类型数据

代码如下(写):

#include <stdio.h>
#include <stdlib.h>
//利用fwrite()写数据
int main()
{
    FILE * fp;
    int buffer[] = {9, 5, 2, 7};
    if((fp = fopen ("D:\\number.txt", "wb"))!=NULL){
        fwrite (buffer, sizeof(int), 4, fp);
        fclose (fp);
    }
    puts("已将数据按照二进制的形式存入文件");
    return 0;
}


结果如下(写):

已将数据按照二进制的形式存入文件


代码如下(读):

#include <stdio.h>
#include <stdlib.h>
//利用fread()读数据
int main()
{
    int i;
    FILE * fp;
    int buffer[4];
    if((fp = fopen ("D:\\number.txt", "rb"))!=NULL){
        fread(buffer, sizeof(int), 4, fp);
        fclose (fp);
    }
    for(i=0;i<4;i++){
        printf("%d ",buffer[i]);
    }
    return 0;
}


结果如下(读):

9 5 2 7


练习:利用fread( )和fwrite( )读写结构体

代码如下(写):

#include <stdio.h>
#include <stdlib.h>
//利用fwrite()写数据
typedef struct{
    int age;
    char name[20];
}Student;

int main()
{
    int i;
    FILE * fp;
    Student stu1={18,"zxx"};
    Student stu2={19,"hmm"};
    Student stu3={29,"lqn"};
    Student studentArray[3]={stu1,stu2,stu3};
    if((fp = fopen ("D:\\student.txt", "wb"))!=NULL){
        for(i=0;i<3;i++){
            fwrite(&studentArray[i],sizeof(Student),1,fp);
        }
        puts("已将结构体类型数据按照二进制的形式存入文件");
        fclose (fp);
    }
    return 0;
}


结果如下(写):

已将结构体类型数据按照二进制的形式存入文件


代码如下(读):

#include <stdio.h>
#include <stdlib.h>
//利用fread()读数据
typedef struct{
    int age;
    char name[20];
}Student;

int main()
{
    FILE *fp;
    Student stu;
    if((fp = fopen ("D:\\student.txt", "rb"))!=NULL){
        while((fread(&stu,sizeof(Student),1,fp))==1){
            printf("%d %s\n",stu.age,stu.name);
        }
        fclose(fp);
    }
    return 0;
}


结果如下(读):

18 zxx
19 hmm
29 lqn


9、fread( )和fwrite( )使用小结

打开文件的模式为“rb”或者“wb”表示按照二进制读或者按照二进制写
按照二进制方式将数据存入硬盘中文件,我们打开该文件后是无法读懂的
每次读或写数据后指针都会指向下一个待写或者待读数据的位置
在利用fread( )和fwrite( )读写完数据后需调用fclose( )方法关闭流
--------------------- 
作者:谷哥的小弟 
来源:CSDN 
原文:https://blog.csdn.net/lfdfhl/article/details/83752060 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/qq_41785863/article/details/83988329
今日推荐