• C语言【文件】


    目录

     概念

     文件名

     文件的打开和关闭

    fopen

    fclose 

    输入输出函数 

     fputc

    fgetc

    fputs

    fgets 

    fprintf

    fscanf

    fwrite

    fread

    三种流

    scanf和sprintf

     结构体转化

    ​编辑

     文件的随机读写

    fseek

    ftell

    rewind

    文本文件和二进制文件

    文件读取结束的判定

    文件缓冲区


     概念

    文件的作用:文件是存放于硬盘中的,使数据能够持久化保存。

    数据文件文件的内容不一定是程序,它可以是程序运行时产生的读写数据。

    有时后我们会将文件输出到磁盘上,在需要的时候再从磁盘上把数据读取到内存中使用。

     文件名

    一个文件需要一个唯一的文件标识:
    文件路径 + 文件名主干 + 文件后缀

    例: c:\code\test.txt

     文件的打开和关闭
     

    为了方便访问文件中的数据,每个被使用的文件都在内存中开辟了一个相应的文件信息区,记录文件名文件的状态、文件路径等)。这个文件信息区被存放在一个结构体变量中,通过文件指针可以访问这块区域,并对文件实施各种操作。

    FILE* pf;//文件指针变量

     

    fopen

    根据文件名打开打开文件,并返回一个FILE*类型的指针。

    文件操作模式类型(第二个参数): 

    注意文件路径可以是相对或绝对路径
     

    fclose 

    关闭文件,和fopen一起使用。 

    输入输出函数 

     fputc

    意为将字符写入到文件中。

    返回值: 为字符的ASCII码值(非负值)。失败返回-1。

     利用返回值写入的数据依次打印到屏幕上:

    1. int main()
    2. {
    3. //打开文件
    4. FILE* pf = fopen("text.txt", "w");
    5. if (NULL == pf)
    6. {
    7. perror("fopen");
    8. return 1;
    9. }
    10. //写文件
    11. int i = 0;
    12. for (i = 0; i < 26; i++)
    13. {
    14. putchar(fputc('a'+i, pf));
    15. }
    16. fclose(pf);
    17. pf = NULL;
    18. return 0;
    19. }

    fgetc

    意为获取文件中的字符返回它的ascii码在使用fgetc前,要确保文件状态为 r 专注输入数据而非w专注输出数据,否则会导致读取失败。

     pf指针具有Placeholder指针可以遍历文件:

     

    1. int main()
    2. {
    3. //打开文件
    4. FILE* pf = fopen("text.txt", "r");
    5. if (NULL == pf)
    6. {
    7. perror("fopen");
    8. return 1;
    9. }
    10. int ch = 0;
    11. while ((ch = fgetc(pf)) != EOF)//意为读取文件所有内容之后返回-1(文件末尾)
    12. {
    13. printf("%c", ch);
    14. }
    15. fclose(pf);
    16. pf = NULL;
    17. return 0;
    18. }

    fputs

    作用:将字符串写入到文件中,想达到按行写入可以主动加上\n

    返回值:成功时返回非负值,失败返回-1。

     

    fgets 

    作用:从文件中依次读取字符串,遇到\n或者读取(num-1)个数字后终止读取。也就是说它只读取num-1个数字并在num或\n后处自动补上\0

    返回值:str的首地址,若失败返回NULL。

      

    区分fgets和gets

    前者是从中读取数据,后者是从键盘中读取数据,当fgets读取对象是stdin时,是近似于gets函数的。不同的是读取\n时,fgets会将其读取并保存。而gets函数会将其读取并丢弃。

    原因:我觉得应该时fputs输出数据时是需要手动添加\n才能达到换行的效果,所以fgets会保留,而gets函数自动加换行是为了区分不同数据。

    fprintf

     从文件流中按照一定格式写数据。

     例如复杂的结构体

    1. struct S
    2. {
    3. char name[20];
    4. int age;
    5. float score;
    6. };


    fscanf

     从文件流中按照一定格式读数据。

     

    当然,你也可以用前面的文件读取函数进行读取:

    1. char arr[20] = { 0 };
    2. fgets(arr,20,pf);//也行
    3. printf("%s",arr);

    fwrite

    对文件进行二进制写入。[适用于所有类型]

    第一个参数为写入数据的地址,第二个参数为数据的大小,第三个参数为数据个数。类似于memcpy一个字节一个字节拷贝数据。

     注意读写二进制文件属性要变为 ”wb"

     

    这下知道文件中为什么会有乱码了吧~ 

    fread

    对文件进行二进制读取,会返回读取成功的count个数。

     

    三种流

    而文件输入输出函数适用于所有流它们对数据的操作可以不局限于文件。也就是说可以用它们实现像scanf、printf之类函数的功能:

    1. fprintf(stdout, "hello world");//屏幕
    2. int a = 0;
    3. fscanf(stdin,"%d" ,a);//键盘

    scanf和sprintf

    sscanf按照一定格式将字符串转换为特定格式

    sprintf将其他数据类型按照指定的格式转换成字符串。【后面自动补‘\0’】

     结构体转化

    将结构体转化成字符串:

     将字符串转化成结构体:

     文件的随机读写

    fseek

    作用:将流里文件指针设置起始位置偏移量,按此偏移量的位置进行读写操作。

     

    SEEK_END为末尾数据的下一个位置 

    1. int ch = fgetc(pf);
    2. putchar(ch);
    3. //a
    4. fseek(pf,-2,SEEK_END);//反向找
    5. ch = fgetc(pf);
    6. putchar(ch);
    7. //e
    8. fseek(pf, 0, SEEK_SET);//回到起始位置
    9. ch = fgetc(pf);
    10. putchar(ch);
    11. //a
    12. //查找完a后指针位置会向后增1
    13. fseek(pf, 3, SEEK_CUR);//b-->cde
    14. ch = fgetc(pf);
    15. putchar(ch);
    16. //e

    ftell

    返回当前文件指针所指向的位置(偏移量)。

    rewind

     将文件指针设置成最开始的位置。

    文本文件和二进制文件

    数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是 二进制文件 。(乱码)
    字符一律以 ASCII 形式存储,数值型数据既可以用 ASCII 形式存储,也可以使用二进制形式存储。

    对于整数10000,以ASCII码存储为5个字节,而二进制存储只占4和字节。

    文件读取结束的判定

    牢记:在文件读取过程中,不能用 feof 函数的返回值直接用来判断文件的是否结束。
    而是 应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
    • fgetc 判断是否为 EOF .
    • fgets 判断返回值是否为 NULL .
    • fread判断返回值是否小于实际要读的个数。

    fgetc: 

    1. int main(void)
    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)
    11.   {
    12.       putchar(c);
    13.   }
    14.    if (ferror(fp))
    15.        puts("I/O error when reading");
    16.    else if (feof(fp))
    17.        puts("End of file reached successfully");
    18.    fclose(fp);
    19. }

     二进制:

    1. #include
    2. enum { SIZE = 5 };
    3. int main(void)
    4. {
    5.    double a[SIZE] = {1.,2.,3.,4.,5.};
    6.    FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式
    7.    fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组
    8.    fclose(fp);
    9.    double b[SIZE];
    10.    fp = fopen("test.bin","rb");
    11.    size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组
    12.    if(ret_code == SIZE) {
    13.        puts("Array read successfully, contents: ");
    14.        for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
    15.        putchar('\n');
    16.   } else {
    17.       if (feof(fp))
    18.          printf("Error reading test.bin: unexpected end of file\n");
    19.       else if (ferror(fp)) {
    20.           perror("Error reading test.bin");
    21.       }
    22.   }
    23.    fclose(fp);
    24. }

    文件缓冲区

    所谓文件缓冲区,就是在使用文件时,系统会为每个文件分配一块缓冲区用于存放数据,当内存向磁盘中传输数据或当磁盘向内存中传输数据的时候,这些数据会一个一个被加载到缓存区上,再一齐被加载到内存或磁盘上。

     

    作用:将缓存区中的数据输出到流里(stdout、FILE) 

    1. #include
    2. #include
    3. int main()
    4. {
    5. FILE* pf = fopen("text.txt", "w");
    6. if (NULL == pf)
    7. {
    8. perror("fopen");
    9. return 1;
    10. }
    11. int a = 10000;
    12. fwrite(&a, sizeof(int), 1, pf);//二进制
    13. printf("内容存放在缓冲区,此时打开文件无内容\n");
    14. Sleep(10000);//休眠10秒,数据已经在缓存区上了
    15. fflush(pf);//刷新缓冲区
    16. printf("再打开文件,内容已存在\n");
    17. fclose(pf);//注:fclose在关闭文件的时候,也会刷新缓冲区
    18. pf = NULL;
    19. }

    注:读取写入数据时遇到\n或fclose也会刷新缓冲区。 

    所以在我们对文件进行操作时别忘了执行刷新缓冲区文件关闭操作!否则可能造成文件读写出错。

  • 相关阅读:
    java计算机毕业设计智慧物业管理系统源程序+mysql+系统+lw文档+远程调试
    springBoot集成SpringSecurity(随笔记录)
    智云通CRM:大客户销售流程,新手也能快速入门
    sonarqube、gitlab、gitlab-runner集成,实现代码push后立即扫描代码生成报告
    pytest合集(11)— conftest.py文件
    数字孪生高峰论坛关于可视化技术解决方案建设
    3.运行项目
    Jmeter基础入门教程【23】--常用功能详解:断言持续时间
    WPF Datagrid Header数据绑定,表头复选框实现全选、全否、部分选中,根据条目动态变化
    圆相交 马蹄集
  • 原文地址:https://blog.csdn.net/dwededewde/article/details/133892627