zoukankan      html  css  js  c++  java
  • 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是忽略的。

     

  • 相关阅读:
    【3y】从零单排学Redis【青铜】
    【Java】几道常见的秋招面试题
    【Java】广州三本秋招经历
    两个月的Java实习结束,继续努力
    外行人都能看懂的SpringCloud,错过了血亏!
    【Java】留下没有基础眼泪的面试题
    【Java】几道让你拿offer的知识点
    Java多线程打辅助的三个小伙子
    数据库两大神器【索引和锁】
    Linux网络管理
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/6628806.html
Copyright © 2011-2022 走看看