• 深度解析C语言文件操作以及常见问题


    作者:~小明学编程

    文章专栏:C语言基础知识

    目之所及皆为回忆,心之所向皆为过往
    在这里插入图片描述

    目录

    为什么我们要使用文件

    文件的打开和关闭

    文件指针

    文件的打开和关闭

    文件的打开方式

    文件的顺序读写 

    fgetc

    fputc

    fputs

    fgets

    fscanf

    fprintf

    fwrite

    fread

    文件的随机读取

    fseek

     ftell

    rewind 

    文件读取结束的判定

    大怨种feof


    为什么我们要使用文件

    在我们写程序的时候,大家一定发现了一个问题就是我们的程序在运行完了之后就啥也没有了就如我们的通讯录小程序我们在运行程序的时候会对其输入很多的人物信息然后我们可以对其进行修改查询等操作,但是当我们结束该程序的时候我们所输入的数据会随着我们的程序的结束而被程序给释放掉,那么我们如何解决该问题呢?这时我们会想到要是我们能有一个文件存储这些信息,当我们下次再次打开该程序的时候接着读取上一次的信息就好了,这便是我们本次要介绍的内容,我们通过一些函数直接操作文件的读写。

    文件的打开和关闭

    文件指针

    缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
    每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE.
    使用方式
    FILE* pf;//文件指针变量
    定义 pf 是一个指向 FILE 类型数据的指针变量。可以使 pf 指向某个文件的文件信息区(是一个结构体变
    量)。通过该文件信息区中的信息就能够访问该文件。也就是说, 通过文件指针变量能够找到与它关联 的文件。

    文件的打开和关闭

    文件在读写之前应该先 打开文件 ,在使用结束之后应该 关闭文件
    在编写程序的时候,在打开文件的同时,都会返回一个 FILE* 的指针变量指向该文件,也相当于建立了指 针和文件的关系, ANSIC 规定使用 fopen 函数来打开文件, fclose 来关闭文件。
    1. int main()
    2. {
    3. int a = 10000;
    4. FILE* pf = fopen("test.txt", "wb");//打开文件
    5. fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
    6. fclose(pf);//关闭文件
    7. pf = NULL;
    8. return 0;
    9. }

    文件的打开方式

    文件的顺序读写 

    下面给大家具体介绍几个文件常用函数

    fgetc

     函数的功能主要就是从标准流中读取一个字符然后写入文件中

    1. int main()
    2. {
    3. FILE* pw = fopen("test.txt", "w");
    4. if (pw == NULL)
    5. {
    6. printf("%s\n", strerror(errno));
    7. }
    8. fputc('h', pw);
    9. fputc('a', pw);
    10. fputc('h', pw);
    11. fputc('a', pw);
    12. fclose(pw);
    13. pw = NULL;
    14. printf("读取完毕!\n");
    15. return 0;
    16. }

    fputc

    函数的主要功能就是从文件中读出一个字符
    1. int main()
    2. {
    3. FILE* pw = fopen("test.txt", "r");
    4. if (pw == NULL)
    5. {
    6. printf("%s\n", strerror(errno));
    7. }
    8. printf("%c", fgetc(pw));
    9. printf("%c", fgetc(pw));
    10. printf("%c", fgetc(pw));
    11. printf("%c", fgetc(pw));
    12. fclose(pw);
    13. pw = NULL;
    14. printf("读取完毕!");
    15. return 0;
    16. }

    通过fgetc函数我们将刚刚读入的字符再次的读出来。

    这里说明一下,大家可能会觉得我们四个相同的输出语句为什么却读的不同的内容
    这是因为无论我们是读入还是读出,当我们读完第一个字符的时候我们的内部文件指针会自动的指向下一个字符所以我们才会读出不同的内容。

    fputs

     函数的功能主要是写入一个字符串进入我们的文件之中,其中有两个参数,一个是我们的字符串地址,还有一个是文件指针

    1. int main()
    2. {
    3. char str[10]={0};
    4. FILE* pw = fopen("test.txt", "w");
    5. if (pw == NULL)
    6. {
    7. printf("%s\n", strerror(errno));
    8. }
    9. //fgets(str, 10, pw);
    10. //printf("%s", str);
    11. //fgets(str, 10, pw);
    12. //printf("%s", str);
    13. fputs("hello\n", pw);
    14. fputs("world", pw);
    15. fclose(pw);
    16. pw = NULL;
    17. return 0;
    18. }

    fgets

    函数的主要功能就是 从我们的流也就是文件中读取字符串,我们可以看到该函数一共有三个参数,分别是把我们读取的字符串要放入的地址,读取的个数,以及我们的文件指针。

    1. int main()
    2. {
    3. char str[10]={0};
    4. FILE* pw = fopen("test.txt", "r");
    5. if (pw == NULL)
    6. {
    7. printf("%s\n", strerror(errno));
    8. }
    9. fgets(str, 10, pw);
    10. printf("%s", str);
    11. fgets(str, 10, pw);
    12. printf("%s", str);
    13. //fputs("hello\n", pw);
    14. //fputs("world", pw);
    15. fclose(pw);
    16. pw = NULL;
    17. return 0;
    18. }

    fscanf

     函数的主要功能就是格式化的从文件中输入想要的数据

    1. struct S
    2. {
    3. char name[20];
    4. int age;
    5. double score;
    6. };
    7. int main()
    8. {
    9. struct S s = { 0 };
    10. FILE* p = fopen("text.txt", "r");
    11. if (p == NULL)
    12. {
    13. printf("%s", strerror(errno));
    14. }
    15. if (p == 0)
    16. {
    17. return 1;
    18. }
    19. fscanf(p, "%s %d %f", s.name, &(s.age), &(s.score));
    20. printf("%s %d %f", s.name, s.age, s.score);
    21. fclose(p);
    22. p == NULL;
    23. return 0;
    24. }

    fprintf

     函数的主要功能就是格式化的将数据输出到文件之中

    1. struct S
    2. {
    3. char name[20];
    4. int age;
    5. double score;
    6. };
    7. int main()
    8. {
    9. struct S s = { "张三",20,100.0 };
    10. FILE* p = fopen("text.txt", "w");
    11. if (p == NULL)
    12. {
    13. printf("%s", strerror(errno));
    14. }
    15. if (p == 0)
    16. {
    17. return 1;
    18. }
    19. fprintf(p,"%s %d %f", s.name, s.age, s.score);
    20. fclose(p);
    21. p == NULL;
    22. return 0;
    23. }

    fwrite

     函数主要功能是以二进制的形式写入文件数据

    其中的参数分别是要写入的项目地址,字节的大小,要写入的最大项目数和文件指针

    1. struct S
    2. {
    3. char name[20];
    4. int age;
    5. double score;
    6. };
    7. int main()
    8. {
    9. struct S s = { "张三",20,60 };
    10. FILE* pf = fopen("test.txt", "wb");
    11. if (pf == NULL)
    12. {
    13. return 1;
    14. }
    15. fwrite(&s, sizeof(struct S), 1, pf);
    16. return 0;
    17. }

    fread

     函数的主要功能是从流中以二进制形式读入数据,参数和fwrite一样。

    1. struct S
    2. {
    3. char name[20];
    4. int age;
    5. double score;
    6. };
    7. int main()
    8. {
    9. struct S s = { 0 };
    10. FILE* pf = fopen("test.txt", "rb");
    11. if (pf == NULL)
    12. {
    13. return 1;
    14. }
    15. fread(&s, sizeof(struct S), 1, pf);
    16. printf("%s %d %.1lf", s.name, s.age, s.score);
    17. return 0;
    18. }

    文件的随机读取

    fseek

     该函数可以让我们从指定的位置读取文件的内容,传参以此是文件指针,偏移量和读取的位置

    1. int main()
    2. {
    3. FILE* p = fopen("test.txt", "r");
    4. if (p == NULL)
    5. {
    6. return 1;
    7. }
    8. fseek(p, 2, SEEK_CUR);
    9. printf("%c", fgetc(p));
    10. fclose(p);
    11. p = NULL;
    12. return 0;
    13. }

    我们可以看到我们的偏移量是2,读取位置是当前文件指针的位置

     ftell

    函数的主要作用是返回一个文件指针相对于起始位置的偏移量

    1. int main()
    2. {
    3. FILE* p = fopen("test.txt", "r");
    4. if (p == NULL)
    5. {
    6. return 1;
    7. }
    8. fseek(p, 2, SEEK_CUR);
    9. printf("%c\n", fgetc(p));
    10. int ret = ftell(p);
    11. printf("%d", ret);
    12. fclose(p);
    13. p = NULL;
    14. return 0;
    15. }

    我们可以看到返回的是3。

    rewind 

    此函数的目的是让文件指针重新回到起始的位置。

    文件读取结束的判定

    大怨种feof

    对feof函数最大的误解就是觉得它是用来判断判断文件是否结束的,然而它的作用并不是如此,用它的时候文件一定是读取结束只是它可以告诉我们文件读取结束是因为什么是文件读完了还是文件读取失败了。

    1. 文本文件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
    例如:
    fgetc 判断是否为 EOF .
    fgets 判断返回值是否为 NULL .
    2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
    例如:
    fread 判断返回值是否小于实际要读的个数。
    1. int main()
    2. {
    3. int c; // 注意:int,非char,要求处理EOF
    4. FILE* fp = fopen("test.txt", "r");
    5. if (!fp) {
    6. perror("File opening failed");
    7. return EXIT_FAILURE;
    8. }
    9. //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    10. while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
    11. {
    12. putchar(c);
    13. }
    14. //判断是什么原因结束的
    15. if (ferror(fp))
    16. puts("I/O error when reading");
    17. else if (feof(fp))
    18. puts("End of file reached successfully");
    19. fclose(fp);
    20. return 0;
    21. }

  • 相关阅读:
    nvm使用
    java基于ssm网上超市购物商城-计算机毕业设计
    SpringBoot加载配置文件的顺序
    python解析xml遇到的问题分享(命名空间有关)
    render-props和高阶组件
    【LeetCode】169. 多数元素
    数电实验-----实现74LS153芯片扩展为8选1数据选择器以及应用(Quartus II )
    《数据结构》复试问答题总结
    一文教你在 centos7 下安装 Oracle19 C(完整版)
    JS 中 对象 基础认识
  • 原文地址:https://blog.csdn.net/m0_56911284/article/details/126025381