• C语言基础(20)-文件操作(fopen,getc,fclose)


    一.文件操作

    读文件的顺序:

    1.先打开文件

    2.读写文件

    3.关闭文件

    1.1 fopen

    FILE *fopen( const char *path, const char *mode );
    
    函数说明:
    1.path就是指定打开文件的路径,可以是相对路径,也可以绝对路径。mode代表打开文件的方式 2.fopen打开成功,返回FILE的有效地址,失败返回NULL. 3.fopen返回的指针是不能自己计算的,一定是要给C语言文件操作的库函数操作的

    以只读方式打开文件,该文件必须存在,文件必须是可读的。

    
    

    r+ 以可读写方式打开文件,该文件必须存在。

    
    

    rb+ 读写打开一个二进制文件,允许读写数据,文件必须存在。

    
    

    rw+ 读写打开一个文本文件,允许读和写。

    
    

    打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。

    
    

    w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

    
    

    以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)

    
    

    a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 (原来的EOF符不保留)

     

    1.2 getc

    int getc( FILE *stream ); 
    函数说明:
    1.getc的功能是一个字节一个字节的读取文件内容
    2.stream代表返回的FILE有效地址

    1.3 fclose

    int fclose( FILE *stream );
    函数说明:
    函数fclose()关闭给出的文件流, 释放已关联到流的所有缓冲区. fclose()执行成功时返回0,否则返回EOF.

    示例代码:

    #include <stdlib.h>
    #include <stdio.h>
    
    #pragma warning(disable:4996)
    
    void fopenUseDemo(void);
    
    
    int main()
    {
        
        fopenUseDemo();
        system("pause");
        return 0;
    
    }
    
    
    
    void fopenUseDemo(void)
    {
        // p 这个指针一般不用来计算,主要的用处是给C语言库函数作为参数
        // 1.打开文件
        FILE *p = fopen("E:\CrackCaptcha.log","r");
        if (p == NULL) {
            printf("文件打开失败
    ");
        }else {
            //printf("文件打开成功
    ");
            //char c = getc(p);
            //printf("%c
    ",c); // 输出2
            //char d = getc(p); // 第二次调用getc的时候,getc会自动从第二个BYTE开始读取文件的内容,这个是不需要我们通过代码干预的。
            //printf("%c
    ", d);// 输出0
            
            // 2.读取文件内容
            char c = 0;
            while (c != EOF) // 只要不是文件结尾,那么就一直循环
            {
                c = getc(p);
                printf("%c",c);
            }
    
            // 3.关闭文件
            fclose(p); // p代表fopen成功返回的值
        }
    
    }

    输出结果:

    1.4 putc

    int fputc( int ch, FILE *stream );
    函数说明:
    1.第一个参数是要写入的char 2.第二个参数是fopen返回的指针

    示例代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    void fopenUseDemo1(void);
    void fopenUseDemo2(void);
    
    // int fputc( int ch, FILE *stream );
    // 第一个参数是要写入的char
    // 第二个参数是fopen返回的指针
    
    void fopenUseDemo1(void)
    {
        FILE *p = fopen("E:\xp.chen.txt","w");
        if (p)
        {
            printf("执行成功
    ");
            char a[100] = "hello world";
            int len = strlen(a);
            for (int i = 0; i < len; i++)
                putc(a[i],p);
            fclose(p);
        }
    
    }
    
    
    // 实现简单的文件拷贝
    void fopenUseDemo2(void)
    {
        FILE *p1 = fopen("E:\xp.chen.txt","r");
        FILE *p2 = fopen("E:\naruto.txt","w");
        if (p1&&p2)
        {
            // 读取p1,将读取到的内容写入p2,就实现了文件的拷贝
            char c = 0;
            while (1)
            {
                char c = getc(p1); // 从p1中读一个字节
                if (c == EOF)
                    break;
                putc(c,p2); // 将p1中读到的字节写到p2
            }
            fclose(p1);
            fclose(p2);
        }
    
        
    }

    1.5 fgets

    char *fgets( char *str, int num, FILE *stream );
    函数说明:
    1.第一个参数代表待存储的字符串,第二个参数代表待存储的字符串的长度,第三个参数代表打开的文件路径

    示例Demo:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    
    void fgetsUseDemo(void);
    
    void fgetsUseDemo(void)
    {
        
        FILE *p = fopen("E:\naruto.txt","r");
        if (p)
        {
            //char a[100] = {0};
            //fgets(a, sizeof(a), p);//从p中读一行,包括行尾的回车
            //printf("%s
    ",a);
    
            // 示例1:循环读取文件内容
            //while (1)
            //{
            //    char a[100] = {0};
            //    fgets(a,sizeof(a),p); // 从p中读一行,包括行尾的回车
            //    if (feof(p)) // 如果p已经到了文件最后,feof返回true
            //        break;
            //    printf("%s",a);
            //}
    
            char a[100] = {0};
            fgets(a,sizeof(a),p);
            printf("%s",a);
    
            // 示例2:循环读取所有文件内容
            while (!feof(p))
            {
                char a[100] = {0};
                fgets(a,sizeof(a),p);
                printf("%s",a);
            }
    
            fclose(p);
        }
    
    }
    int feof( FILE *stream );
    注意:
    1.如果文件已经到达文件结尾,feof()函数返回true 2.传入的参数是fopen返回的文件指针

    1.6 fputs

    int fputs( const char *str, FILE *stream );
    函数说明:
    1. 第一个参数代表需要写入的内容,第二个参数代表将要写入的文件
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    void fputsUseDmeo(void);
    
    void fputsUseDmeo(void)
    {
        
        FILE *p = fopen("E:\xp.chen.txt","w");
        if (p)
        {
            char a[100] = "仙法!超大玉螺旋手里剑";
            fputs(a,p);
        }
    
    
    }

    1.7 fprintf()

     int fprintf( FILE *stream, const char *format, ... );
     函数说明
     1.用法和printf一样,只是多了第一个参数,该参数代表打开的文件指针
    // int fprintf( FILE *stream, const char *format, ... );
    void fprintfUseDemo(void)
    {
        FILE *p = fopen("E:\temp.txt","w");
        char a[100] = "hello";
        fprintf(p,"%s",a); // 用法和printf一样,只是多了第一个参数,参数是打开的文件指针
    
        int a1 = 4;
        int a2 = 5;
    
        /*sprintf(a,"%d%d",a1,a2);
        fputs(a,p);*/
    
        fprintf(p,"%d,%d",a1,a2);
        fclose(p);
        
    }

    1.8 fscanf

    int fscanf( FILE *stream, const char *format, ... );
    函数说明:
    1.第一个参数代表打开的文件指针
    2.第二个参数代表匹配的文本
    3.第三个参数代表需要赋值的变量指针。

    示例代码:

    假设E盘下有有一文本文件为xp.chen.txt,内容为:

    则可通过fscanf来计算以上两个表达式的和

    void fscanfUseDemo1(void)
    {
    
        FILE *p = fopen("E:\xp.chen.txt","r");
        int a1, a2;
        fscanf(p,"%d+%d",&a1,&a2);
        //printf("a1=%d, a2=%d
    ",a1,a2);
        printf("%d
    ",a1+a2); // 计算当前两个数的和
        fscanf(p, "%d+%d", &a1, &a2);
        //printf("a1=%d, a2=%d
    ", a1, a2);
        printf("%d
    ",a1+a2);
        fclose(p);
    
    }

    1.9 stat()

    int  stat(const char * _Filename, struct stat * _Stat)
    函数说明
    1.该函数用于获取当前文件的状态
    2.第一个参数代表当前文件的完整路径,第二个参数代表包含当前文件状态的结构体指针。

    示例代码:

    void statFuntionUseDemio(void)
    {
    
        struct stat fileStates = {0};
        struct stat *p = &fileStates;
        const char *filePath = "E:\xp.chen.txt";
    
        stat(filePath,p);
    
        _off_t fileSize = fileStates.st_size; // _off_t其实就是long类型
        printf("当前这个文件的大小为:%ld
    ",fileSize);
    
    }

    输出结果:

     

    同时通过该函数可以获取文件的其它状态信息(文件大小,最后一次修改时间,文件属性...)

    1.10 fwrite()

    int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
    函数说明
    1.该函数用于写二进制数据到文件
    2.第一个参数代表待写数据的内存地址
    3.第二个参数代表写多少个单位
    4.第三个参数代表每个单位的大小
    5.第四个参数是fopen返回的文件指针。

    示例代码:

    void fwriteUseDemo1(void)
    {
        int array[10] = {1,2,3,4,5,6,7,8,9,10};
        FILE *file = fopen("E:\xp.chen.data","wb");
        fwrite(array,1,sizeof(array),file);
        fclose(file);
    
    }

    1.11 fread()

    int fread( void *buffer, size_t size, size_t num, FILE *stream );
    函数说明
    该函数用于读取二进制文件
    1.第一个参数代表将要读入的buffer
    2.第二个参数代表读多少个单位
    3.第三个参数代表每个单位的大小
    4.第四个参数代表待读取文件的路径。

    示例Demo1:

    // 读取二进制文件内容
    void freadUseDemo(void)
    {
    
        FILE *p = fopen("E:\xp.chen.data","rb");
        while (!feof(p))
        {
            int a;
            int rec = fread(&a,sizeof(a),1,p); // 一个单位是1个字节,fread的返回值代表读取了多少个单位,而不是字节
            //printf("%d
    ",a);
            printf("rec=%d,a=%d
    ",rec,a);
        }
        
        fclose(p);
    
    }

    输出结果:

    示例Demo2:

    void freadUseDemo1(void)
    {
        FILE *p = fopen("E:\xp.chen.data","rb");
        while (1)
        {
            int a;
            if (fread(&a, 1, sizeof(a), p) == 0) // 当读取的单位数为0的时候结束读取
                break;
            printf("a = %d
    ",a);
        }
    
    }

    输出结果:

    示例Demo3:

    // 实现文件拷贝
    void freadUseDemo2(void)
    {
        
        FILE *p1 = fopen("E:\loginsdk.jar","rb");
        FILE *p2 = fopen("E:\xxx.jar","wb");
        if (p1 == NULL)
            return;
        if (p2 == NULL)
            return;
        while (1)
        {
            int a;
            int rc = fread(&a,1,sizeof(a),p1); // rc可以认为是从p1中读取到字节数
            if (rc == 0)
                break;
            fwrite(&a, 1, rc, p2);
            
        }
        fclose(p1);
        fclose(p2);
    
    }

    1.12 fseek()和ftell()

    int fseek( FILE *stream, long offset, int origin );
    函数说明
    1.第一个参数代表fopen打开的文件路径
    2.第二个参数代表位移
    3.第三个参数代表从什么地方开始

    ftell()

    long ftell( FILE *stream );
    函数说明
    1.ftell的功能可以知道指针当前在文件的什么地方

    示例代码:

    //  int fseek( FILE *stream, long offset, int origin );
    // 第一个参数代表fopen返回的文件指针
    // 第二个参数代表位移
    // 第三个参数代表从什么开始
    void fseekUseDemo(void)
    {
    
        /*char a[10] = {1,2,3,4,5,6,7,8,9,10};
        FILE *p = fopen("E:\xp.chen.dat","wb");
        fwrite(&a,1,sizeof(a),p);
        fclose(p);*/
    
    
        char a[2];
        FILE *p = fopen("E:\xp.chen.dat", "rb");
        // 第一次打开文件的时候,指针位于文件的开始位置
        //fseek(p,0,SEEK_SET);//  代表回到起始位置
        // fseek(p,-4,SEEK_END); 代表从最后往前移动4个字节
        fseek(p,0,SEEK_END); // 回到最后位置
        fseek(p,2,SEEK_SET); // SEEK_SET代表文件开始,这句话的意思就是从文件开始向后移动两个字节
        fread(&a,1,sizeof(a),p); // 所有的C语言文件读写库函数都会自动维护fopen返回的文件指针
        printf("%d,%d
    ",a[0],a[1]);
    
        printf("ftell = %ld
    ",ftell(p)); // ftell的功能可以知道指针当前在文件的什么地方
    
        // 通过下列方式可以计算出文件大小
        // fseek(p,0,SEEK_END); // 先使用SEEK_END将指针移动到文件最后
        // ftell(p);//然后使用ftell获得最后的偏移字节数,也就是文件的大小
        fclose(p);
    
    }

    运行结果:

    1.13 fflush()

    int fflush( FILE *stream );
    函数说明
    1.fflush函数可以将缓冲区中任何未写入的数据立刻写入文件中

    示例代码:

    // 由于fflush是实时将缓冲区的内容写入到磁盘,所有不要大量的使用,但
    // 如果是特别敏感的数据,可以通过fflush写入磁盘,防止由于电脑各种故障,
    // 内存数据丢失
    void fflushFunctionUseDemo(void)
    {
        FILE *p = fopen("E:\xp.chen.txt","w");
        while (1)
        {
            char a[100] = {0};
            scanf("%s",a);
            if (strcmp(a, "exit") == 0)
                break;
            fputs(a,p);
            putc('
    ',p);
            fflush(p); // fflush函数可以将缓冲区中任何未写入的数据立刻写入文件中
        }
        fclose(p);
    }

    运行结果:

    1.14 remove()和rename()

    void remove( const TYPE &val );
    函数说明:
    删除文件,参数为文件路径

    rename()

    int rename( const char *oldfname, const char *newfname );
    函数说明:
    函数rename()更改文件oldfname的名称为newfname. rename()成功时返回0,错误时返回非零. 

    示例代码:

    void removeFunctionUseDemo(void)
    {
        //remove("E:\xp.chen.txt"); // 删除指定文件
        rename("E:\xxx.jar","E:\nimabi.jar");
    }

    二.二进制和文本模式的区别

    1.windows系统中,文本模式下,文件以" "代表换行。若以文本模式打开文件,并用fputs等函数写入换行符" "时,函数会自动在" "前面加上" "。即实际写入文件的是" " 

    2.在类Unix/Linux系统中文本模式下,文件以" "代表换行。所以Linux系统中在文本模式和二进制模式下并无区别。

    3.在windows下,读写文本文件的时候,是不写b的,但读写二进制文件的时候一定要写b,Linux,b是忽略的。

     

  • 相关阅读:
    Spring Boot (20) 拦截器
    Spring Boot (19) servlet、filter、listener
    Spring Boot (18) @Async异步
    Spring Boot (17) 发送邮件
    Spring Boot (16) logback和access日志
    Spring Boot (15) pom.xml设置
    Spring Boot (14) 数据源配置原理
    Spring Boot (13) druid监控
    Spring boot (12) tomcat jdbc连接池
    Spring Boot (11) mybatis 关联映射
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/6628806.html
Copyright © 2020-2023  润新知