C语言文件操作

C语言文件操作

什么是文件

文件就是在磁盘上的一段存储空间

不同文件的格式是不一样的,也就是说文件存储的数据是不同的。比如 txt(文本文件) 存储的是字符数据,png(图片文件) 存储的是颜色标识数据,exe(可执行文件) 存储的都是代码。当然数据的本质都是二进制的 0和1,不同的文件在宏观上都是使用 后缀 来区分的。

所谓文件操作,就是把文件内容读进程序里,然后根据格式进行解析,进行读写等操作。


如何操作文件

一、打开文件

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

使用上面这个函数来打开一个文件。它的原理是在物理内存开辟一块空间,将磁盘中被选定文件的内容复制过来(本质就是一大堆字符串),然后进行操作。当我们操作文件结束之后,再把复制的这一份更新到磁盘空间,最终完成修改。

FILE*                 //返回值是一个文件指针,也就是物理内存上这块空间的首地址
fopen                 //函数名
const char *filepath  //参数1,文件的路径(绝对、相对路径),注意绝对路径的\要进行转义
const char *mode      //参数2,文件的打开方式

当我们对文件的操作结束后,需要在程序中关闭文件。这一步会将我们修改后的文件更新到磁盘空间,把开辟的操作文件内存空间释放。

int fclose( FILE *stream ); //唯一参数,文件指针

二、文件的打开方式

(一)文本模式(默认的打开模式)

  1. r模式:只读模式

    r模式,又称 rt (read text) 模式,通过这种形式打开文件,文件就只能读取,不能修改。且打开的前提要求是文件必须存在,不存在则打开失败,会报错。

  2. w模式:可读可写模式之从头来过

    w模式,又称 wt 模式,通过 w 模式打开的文件,首先会自动擦除原数据。比如文件原来有内容,w 模式打开就会先把文件擦除,重新按照操作写入新数据。

    而当文件不存在的时候,会创建文件

  3. a模式:可读可写模式之狗尾续貂

    a模式,又称 at 模式(append),通过 a 模式打开的文件,不会擦除原有数据,而是在原有内容后面接着写。比如文件有内容,打开文件内容原封不动,如果写入新内容,就会在原有的尾巴上接着写。

    文件不存在的时候,会创建文件

  4. 三种模式的plus版本

    r+模式( r模式plus版本 ),通过这个模式打开文件,可读可写。所以plus之处就是加上了“写”操作。注意前提仍然是文件必须存在。而且 r+ 模式等同 w 模式,都是擦除写。

    同理,w+ 和 a+ 模式就是 w 和 a 模式的plus版本。因为plus之处在于加上“写”操作,所以plus版本和以前没什么变化。

(二)二进制模式(需要指定的模式)

  1. rb模式:只读模式

    rb(read bit)模式,原理同 rt 模式。(文件必须存在)

  2. wb模式:可读可写模式之从头来过

    wb模式,原理同 wt 模式。(文件不存在会创建文件)

  3. ab模式:可读可写模式之狗尾续貂

    ab模式,原理同 ab 模式。(文件不存在会创建文件)

  4. 三种模式的plus版本

    rb+模式( rb 模式plus版本 ),文件可读可写。注意前提仍然是文件必须存在。而且 r+ 模式等同 w 模式,都是擦除写。

    同理,wb+ 和 ab+ 模式没什么变化。


三、操作文件

(一)写

  1. fwrite:一次写入指定字节数
    size_t fwrite(         //返回值是实际写入的字符数(int型),写入失败会返回 0
       const void *buffer, //参数1:要写入文件的数据的首地址,可以是字符串、数组、结构体
       size_t size,        //参数2:sizeof(类型)
       size_t count,       //参数3:数据数量,参数2与参数3相乘得出写入的字节数
       FILE *stream        //参数4:文件指针
    );
    

    举个栗子:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char* str = "I LOVE YOU !";
    
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "w");
    
        fwrite(str, sizeof(char), strlen(str), f);
        fwrite("\n", sizeof(char), 1, f);  // 写入回车
        fwrite(str, sizeof(char), strlen(str), f);
    
        fclose(f);
    
        return 0;
    }
    
  2. fputs:一次写入一行(但它不会自动加换行,换行需要自己在输入字符串尾巴加\n)
    int fputs( const char *str,   FILE *stream );
    
    //返回值:成功返回 0,失败返回EOF(-1)
    //参数1:输入的字符串(只能输入字符串)
    //参数2:文件指针
    

    举个李子:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char* str = "I LOVE YOU !";
    
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "w");
    
        fputs(str, f);
        fputs("\n", f);
        fputs(str, f);
    
        fclose(f);
    
        return 0;
    }
    
  3. fprintf:格式化写入
    int fprintf( 
       FILE *stream,        //文件指针
       const char *format [,//和printf函数一样的参数要求
          argument ]...
    );
    

    举个梨子:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "w");
    
        fprintf(f, "%d,%s,%lf", 12, "hello", 12.34);
        fclose(f);
        //写入内容:12,hello,12.340000
        return 0;
    }
    

(二)读(注意w和r+模式会擦除内容)

  1. fread():一次读指定字节数
    size_t fread(     //返回值是实际读出的字节数
        void *buffer, //参数1:我们自定义的字符数组,文件读出来的内容装在这里
        size_t size,  //参数2:sizeof(类型)
        size_t count, //参数3:数据数量,参数2与参数3相乘等于读出的字节数
     	FILE *stream  //参数4:文件指针
    );
    

    举个例子:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char str[15] = { 0 };
    
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "r");
        
        fread(str, sizeof(char), 12, f);
        puts(str); //I LOVE YOU !
        
        /*while (fread(str, sizeof(char), 1, f))
        {
            printf("%s", str);// I LOVE YOU !
        }*/
        
        fclose(f);
        return 0;
    }
    

    fread()读写结构体:

    #include <stdio.h>
    
    struct Node
    {
        int id;
        char name[10];
        short age;
        double score;
    };
    
    int main()
    {
        //写操作
        struct Node stu1 = { 13,"张三",20,88.8 };
    
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "w");
        fwrite(&stu1, sizeof(stu1), 1, f);
        fclose(f);
    
        //读操作
        struct Node stu2;
    
        FILE* g = fopen("C:\\Users\\13040\\Desktop\\test.txt", "r");
        fread(&stu2, sizeof(stu1), 1, g);
        fclose(f);
        
        return 0;
    }
    //调试发现:stu2{id=13 name=0x000000af711cfc0c "张三" age=20 ...}成功读取
    
  2. fgets():一次读一行
    char *fgets( char *str,  int n,  FILE *stream );
    
    //返回值:就是str的地址
    //参数1:读出来的数据装在哪儿
    //参数2:最大的读取量,不要超过参数1的长度
    //参数3:文件指针
    

    举个例子:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char str[20] = "";
    
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "r");
    
        fgets(str, 20, f);
        puts(str);
        fclose(f);
    
        return 0;
    }
    
  3. fscanf():格式化读(与fprintf配套使用)
    int fscanf( 
       FILE *stream,        //文件指针
       const char *format [,//和scanf函数一样的参数要求
          argument ]... 
    );
    

    举个例子:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int a = 0;
        char str[20] = { 0 };
        double b = 0;
    
        FILE* f = fopen("C:\\Users\\13040\\Desktop\\test.txt", "r");
        
        //先w模式写入,记住字符串连接数字必须用空格隔开,要不然读取的时候字符串不遇空格不停
        //fprintf(f, "%d,%s %lf", 12, "hello", 12.34);
    
        //怎么用fprintf写的,fscanf就得怎么读,格式字符串必须保持一致
        fscanf(f, "%d,%s %lf", &a, str, &b);
    
        printf("%d\n", a);
        printf("%s\n", str);
        printf("%lf", b);
    
        fclose(f);
        
        return 0;
    }
    /*
    12
    hello
    12.340000
    */
    

(三)文件游标指针

为了对读写进行控制,系统为每一个文件设置了一个文件读写游标指针(或称文件读写位置标记),用来指示“接下来要读写的下一个字符的位置”。

一般情况下,在对文本文件进行顺序读写时,文件游标指针指向文件开头,这时进行读操作,就读第一个字符,然后文件游标指针向后移动一个位置,以此类推,遇到文件尾结束。

如果是写操作,则每写完一个数据后,文件游标指针顺序向后移动一个位置,然后下一次写操作时把数据写入新的所指位置,以此类推,直到写完全部数据。

也可以根据需要,人为移动游标指针位置。

  • feof判断文件的游标指针是否位于文件结尾处
    int feof( FILE *stream );
    //参数为文件指针
    //返回值:游标指针没到文件结尾返回 0,到了结尾返回 !0(利用这点可作循环条件)
    
  • fseek设置文件游标指针的位置
    int fseek(    
    FILE *stream,   //参数1:文件指针
       long offset, //参数2:设置文件游标指针指的位置
       int origin   //参数3:具体位置
    ); 
    

    巨蟹李子:

    fseek(f, 0L, SEEK_SET) 	//设置游标指针指向文件起始位置
    
    fseek(f, 10L, SEEK_SET)	//设置游标指针指向起始位置 向右 挪动10个字节处
    
    fseek(f, 10L, SEEK_CUR)	//设置游标指针在当前位置 向右 挪动10个字节处
    
    fseek(f, -10L, SEEK_CUR)//设置游标指针在当前位置 向左 挪动10个字节处
    
    fseek(f, 0L, SEEK_END)	//设置游标指针指向文件结尾位置(最后一个字符后面)
    
    fseek(f, -10L, SEEK_END)//设置游标指针指向结尾 向左 挪动10个字节处
    
  • ftell返回文件游标指针的当前位置
    long ftell( 
       FILE *stream //文件指针
    );
    //返回文件游标指针当前位置的下标(下标从0开始)
    
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值