• C语言下的文件详解


    主要内容

    1. 文件概述
    2. 文件指针
    3. 文件的打开与关闭
    4. 文件的读写

    文件

           把输入和输出的数据以文件的形式保存在计算机的外存储器上,可以确保数据能随时使用,避免反复输入和读取数据 

    文件概述

    1. 文件是指一组相关数据的有序集合
    2. 文件是存储数据的基本单位,可以通过读取文件访问数据。

    分类

    可以按照不同角度对文件进行分类:
    • 按存储介质不同,可以分为磁盘文件、磁带文件、打印文件等
    • 按存储内容不同,可以分为程序文件和数据文件
    • 按访问方式不同,可以分为顺序文件、随机文件和二进制文件
    • 按用户不同,可以分为普通文件和设备文件

    C语言文件分类

    在C语言中,把文件看作是一个字符的序列
    根据数据的组织形式可以分为 ASCII 文件和二进制文件 :
    1 ASCII文件也称为文本文件 ,在磁盘中存放时每个字符对应一个字节,用于存放对应 ASCII
    2 )二进制文件是按二进制的编码方式存放文件,将内存中的数据按照其在内存中的存储形式原样输出到磁盘中存放。 
    短整数 968 00000011 11001000B ):
    • 如果按ASCII码的形式输出则占3个字节(每个字符占1个字节)
    • 而按二进制形式输出,则在磁盘上占2个字节

     

    C 语言版本不同,对文件的处理方式也各有不同,主要有两种方法:

    (1)一种是“缓冲文件系统”

    (2)一种是“非缓冲文件系统”

    缓冲文件系统

    •缓冲文件系统会自动在内存中为每一个正在使用的文件分配一个缓冲区
    在写文件时,先将数据放入缓冲区,当缓冲区存满数据后才将缓冲区中的数据写入文件。
    在读文件时,先一次将一部分数据读入缓冲区,当缓冲区存满数据后才将数据送到程序数据区。
    缓冲区大小由 C 语言的版本确定,一般为 512 字节 

    非缓冲文件系统

    非缓冲文件系统就是系统不会在内存中为文件分配缓冲区,所有的文件操作是直接跟文件打交道,这会导致系统整体效率下降

    文件输入输出函数

    ANSI C 规定了标准的输入输出函数用于文件读写,它们的声明在 stdio.h 文件中

    文件指针

    在缓冲文件系统中,每个文件都在内存中分配一个缓冲区,用来存放文件信息
    信息被存放在一个结构体中,该结构体由系统定义,命名为FILE
    1. typedef struct
    2. { int level; //缓冲区“满”或“空”的标志
    3. unsigned flags; //文件状态标志
    4. char fd; //文件描述
    5. unsigned char hold; //如果没有缓冲区则不读取字符
    6. int bsize; //缓冲区大小
    7. unsigned char _FAR *buffer; //缓冲区位置
    8. unsigned char _FAR *curp; //指向缓冲区当前数据的指针
    9. unsigned istemp; //临时文件指示器
    10. short token; //用于有效性检查
    11. }FILE;
    文件指针变量是一个文件结构体类型的指针变量。 定义文件类型指针变量的一般形式为
    FILE * 指针变量名 ;
    File *fp;
    // fp是一个指向FILE结构体类型的指针变量

    文件的打开与关闭

    C 语言中文件操作一般包括三个步骤:
    1 )用 fopen 函数打开文件
    2 )进行读写操作
    3 )用 fclose 函数关闭文件

    fopen函数

    fopen 函数用于打开文件,并把结果赋给 FILE 指针变量,它的一般形式为:
            fopen(文件名,文件打开方式);
    “文件名”是要打开的文件名,可以是完整的文件路径

                  FILE *fp;

                 //fp是一个指向FILE结构体类型的指针变量

                 fp = fopen("file_data.txt","r");

                //以只读方式打开文件file_data.txt

    文件打开方式”是打开文件的访问方式

    fopen函数,会由于无法打开指定文件而出现错误。

    如果出错,fopen函数会返回一个空指针值NULLNULLstdio.h中被定义为0)。

     例如以“r”方式打开时,文件不存在,要进行错误处理。

                 FILE *fp;

                 if( (fp = fopen("file_data.txt","r") ) == NULL )

                 {  printf("can not open the file\n");

                 exit(0);

                 }

     fclose函数

    • 在操作完一个文件后要关闭文件指针,以释放缓冲区内存,防止其他误操作
    • 关闭文件就是使文件指针变量不再指向该文件
    • fclose函数的一般形式为:
    fclose (文件类型指针);
    fclose(fp);

    文件的读写

    fputc函数

    • fputc函数的作用是将一个字符写入指定文件中
    • 它的一般形式为:
    fputc (字符型数据,文件指针);

    13.1】从键盘输入文本,并将文本写入磁盘上存储的文本文件file_data.txt中。以字符#作为输入结束标志。

    分析:

    首先打开文件,然后从键盘循环输入字符,如果字符不是结束标志“#”,那么将字符写入文件,否则关闭文件

    1. #include
    2. #include
    3. void main()
    4. { FILE *fp;
    5. char ch;
    6. if( (fp = fopen("file_data.txt","w")) == NULL ) //打开文件
    7. { printf("can not open the file\n");
    8. exit(0); //退出程序,必须包含头文件
    9. }
    10. ch = getchar();
    11. while(ch != '#' )
    12. { fputc(ch,fp); //输出字符
    13. ch = getchar();
    14. }
    15. fclose(fp); //关闭文件
    16. }

     fgetc函数

    fgetc 函数的作用是从指定的文件中读入一个字符,并作为函数的返回值返回,如果读到文件结束符时,则返回一个文件结束标志 EOF (值为 -1 )。
    fgetc 函数的一般形式为:
                           fgetc(文件指针);

    13.2】读取文本文件file_data.txt,并将文件中的内容输出到屏幕上。

    分析:

    首先打开文件,然后反复从文件中读入一个字符,并输出到屏幕,直到文件的结尾,最后关闭文件。

    1. #include
    2. #include
    3. void main()
    4. { FILE *fp;
    5. char ch;
    6. if( (fp = fopen("file_data.txt","r")) == NULL ) //打开文件
    7. { printf("can not open the file\n");
    8. exit(0); //退出程序
    9. }
    10. ch = fgetc(fp); //从文件中读入一个字符
    11. while(ch != EOF )
    12. { putchar(ch);
    13. ch = fgetc(fp); //从文件中读入一个字符
    14. }
    15. fclose(fp); //关闭文件
    16. }

    fputs函数

    fputs 函数的作用是将字符串写入指定文件中
    它的一般形式为:
                   fputs(字符串数据,文件指针);
    字符串数据可以是字符串常量或者字符数组名,写入时字符串最后的‘ \0’ 并不一起写入,也不自动添加回车符。
    如果写入成功,则函数返回值为 0 ,否则返回值为 EOF

    13.3】从键盘输入一串字符串,并将字符串写入文本文件file_data.txt中。

    解决该问题的主要步骤为:

    1)打开文本文件file_data.txt

    2)从键盘输入一串字符串。

    3)将字符串写入文件中。

    5)关闭文件。

    6)结束程序。

    1. #include
    2. #include
    3. void main()
    4. { FILE *fp;
    5. char str[20];
    6. if( (fp = fopen("file_data.txt","w")) == NULL )
    7. { printf("can not open the file\n");
    8. exit(0);
    9. }
    10. printf("input the string: ");
    11. gets(str);
    12. fputs(str,fp); //写入字符串
    13. fclose(fp);
    14. }

    fgets函数

    fgets 函数的作用是从指定文件中读入指定长度的字符串
    它的一般形式为:
                   fgets(字符数组名,n,文件指针);
    指定的长度由整型数据 n 决定。
    从文件中读入 n-1 个字符,然后在最后添加一个‘ \0’ 字符作为字符串结束的标志。
    如果在读完 n-1 个字符之前遇到一个换行符或一个 EOF ,则读入结束。
    最多只能读入 n-1 个字符,读入的字符被放入参数的字符数组中,读入结束后,将字符数组的首地址作为函数返回值

    13.4】读取文本文件file_data.txt中指定长度的文本,长度由键盘输入,并将读取的内容输出到屏幕上。

    解决该问题的主要步骤为:

    1)打开文本文件file_data.txt

    2)从键盘输入要读取的文本长度。

    3)读入数据。

    4)输出数据。

    5)关闭文件。

    6)结束程序。

    1. #include
    2. #include
    3. void main()
    4. { FILE *fp;
    5. char str[20];
    6. int n;
    7. if( (fp = fopen("file_data.txt","r")) == NULL )
    8. { printf("can not open the file\n");
    9. exit(0);
    10. }
    11. printf("input the character's number: ");
    12. scanf("%d",&n);
    13. fgets(str,n+1,fp);
    14. printf("%s\n",str);
    15. fclose(fp);
    16. }

    fprintf函数

    fprintf 函数将数据按指定格式写入指定文件中,与 printf 函数的作用相似。
    它的一般形式为:
              fprintf(文件指针,格式字符串,输出表列);
    1. 【例13.5】将指定数据写入文本文件file_data.txt中。
    2. 编写程序如下:
    3. #include
    4. #include
    5. void main()
    6. { FILE *fp;
    7. int i=10,j=12;
    8. double m=1.5,n=2.345;
    9. char s[]="this is a string";
    10. char c='\n';
    11. if( (fp = fopen("file_data.txt","w")) == NULL )
    12. { printf("can not open the file\n");
    13. exit(0);
    14. }
    15. fprintf(fp,"%s%c",s,c);
    16. fprintf(fp,"%d %d\n",i,j);
    17. fprintf(fp,"%lf %lf\n",m,n);
    18. fclose(fp);
    19. }

    文件中保存的文本与程序中的数据一致,且格式与指定格式相同

    1. 【例13.6】按照每行5个数,将Fibonacci数列的前40个数写入file_data.txt文件中。
    2. 编写程序如下:
    3. #include
    4. #include
    5. void main()
    6. { FILE *fp;
    7. int f[40];
    8. int i;
    9. if( (fp = fopen("file_data.txt","w")) == NULL )
    10. { printf("can not open the file\n");
    11. exit(0);
    12. }
    13. for (i=0;i<=39;i++) //求Fibonacci数列
    14. { if (i==0||i==1)
    15. f[i]=1;
    16. else
    17. f[i]=f[i-2]+f[i-1];
    18. }
    19. for (i=0;i<=39;i++) //写入文件
    20. { if ((i+1)%5==0)
    21. fprintf(fp,"%10d\n",f[i]);
    22. else
    23. fprintf(fp,"%10d",f[i]);
    24. }
    25. fclose(fp);
    26. }

     fscanf函数

    fscanf 函数从指定文件中按指定格式读入数据,与 scanf 函数作用相似。 scanf 是从键盘输入,而 fscanf 是从文件读入。
    fscanf 函数的一般形式为:
    fscanf(文件指针,格式字符串,输入表列);

    13.7】以指定格式读取13.5】中生成的文件file_data.txt中的数据,并输出到屏幕上

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    FILE *fp;
    5.     int i,j; 
    6.     double m,n; 
    7.     char s1[100],s2[100],s3[100],s4[100]; 
    8.     if( (fp = fopen("file_data.txt","r")) == NULL )
    9.     {    printf("can not open the file\n");
    10.         exit(0);
    11.     }
    12.  fscanf(fp,"%s%s%s%s",s1,s2,s3,s4); 
    13. //读入四个单词
    14.     fscanf(fp,"%d%d",&i,&j);
    15.  //读入两个整型数据 
    16.     fscanf(fp,"%lf%lf",&m,&n); 
    17. //读入两个double类型数据
    18.     printf("%s %s %s %s\n",s1,s2,s3,s4); 
    19.     printf("%d %d\n",i,j); 
    20.     printf("%lf %lf\n",m,n);
    21.     fclose(fp);
    22. }

    fwrite函数

    fwrite 函数的作用是将指定长度的数据写入指定文件中。它的一般形式为:
                         fwrite(buffer,size,count,文件指针);
    buffer 是数据块的指针,一个写入数据的内存地址
    size 是每个数据块的字节数
    count 是要写入多少个 size 字节的数据块
    fwrite 函数主要用于写入二进制文件,因此在打开文件的时候需要以“ wb” 方式打开
    1. struct Book_Type
    2. {   char name[10];//书名
    3.   int price;//价格
    4.   char author[10];//作者名
    5. };
    如果要将书的信息写入到磁盘中,如下代码实现:
    1. for(i=0;i<2;i++)
    2. {
    3.   fwrite(&book[i],sizeof(struct Book_Type),1,fp);
    4. }

    13.8】通过键盘输入所有2本书的信息,并存储在文本文件file_data.txt中。

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    struct Book_Type
    5.     {     char name[10];//书名
    6.         int price;//价格
    7.         char author[10];//作者名
    8.     };
    9.     FILE *fp;
    10.     struct Book_Type book[2];
    11.     int i;
    12.     if( (fp = fopen("file_data.txt","wb")) == NULL )
    13.     {    printf("can not open the file\n");
    14.         exit(0);
    15.     }
    16.  printf("input the book info: \n");
    17.     for(i=0;i<2;i++)
    18.     {    scanf("%s%d%s",book[i].name,&book[i].price,book[i].author);   
    19.         fwrite(&book[i],sizeof(struct Book_Type),1,fp);   
    20. //读入一条记录
    21.     }
    22.     fclose(fp);
    23. }

    因为是以二进制方式保存,所以记事本中的内容显示为乱码。

    fread函数

    fread 函数的作用是从指定文件中读入指定长度的数据块。它的一般形式为:
                    fread(buffer,size,count,文件指针);
    buffer 是数据块的指针,一个读入数据的内存地址
    size 是每个数据块的字节数
    count 是要读入多少个 size 字节的数据块。
    fread 函数主要用于读取二进制文件,因此在打开文件的时候需要以“ rb” 方式打开。
    例如:
    fread(data,2,3,fp);
    data 是一个整型数组名,一个整型数据占用 2 个字节的内存空间
    此函数调用的功能是从 fp 所指向的文件中读入 3 次(每次 2 个字节)数据,并存储到整型数组 data

    13.9】13.8】中已经存有book信息的文件打开,读出信息后显示在屏幕上。

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    struct Book_Type
    5.     {     char name[10];//书名
    6.         int price;//价格
    7.         char author[10];//作者名
    8.     };
    9.     FILE *fp;
    10.     struct Book_Type book[2];
    11.     int i;
    12.     if( (fp = fopen("file_data.txt","rb")) == NULL )
    13.     {    printf("can not open the file\n");
    14.         exit(0);
    15.     }
    16.  printf("the book info: \n");   
    17.     for(i=0;i<2;i++)
    18.         fread(&book[i],sizeof(struct Book_Type),1,fp);
    19.     for(i=0;i<2;i++)
    20.         printf("name=%s,price=%d,author=%s\n",
    21.   book[i].name,book[i].price,book[i].author);
    22.     fclose(fp);
    23. }

    rewind函数

    rewind 函数的作用是使位置指针重新返回指定文件的开头。
    它的一般形式为:
                     rewind(文件指针);
    此函数没有返回值。
    在文件操作中会移动文件的位置指针,可以使用 rewind 函数将位置指针回到文件头部。

    13.10】将指定字符串数据写入文本文件file_data.txt中,并将文件的位置指针重新定位到文件开头,读出文件中的第1个字符数据后显示在屏幕上。

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    FILE *fp; 
    5.     char s[]="abcdefghijklmnopqrstuvwxyz";
    6.     char c;
    7.     if( (fp = fopen("file_data.txt","w+")) == NULL )
    8.     {        printf("can not open the file\n");
    9.         exit(0);
    10.     }
    11.     fprintf(fp,"%s",s);  //向文件中写入字符串
    12.     rewind(fp);  //指针返回开始
    13.     fscanf(fp,"%c",&c); //读入一个字符
    14.     printf("The first character is: %c\n",c);
    15.     fclose(fp);
    16. }

     fseek函数

    fseek 函数的作用是将文件的位置指针移到指定位置
    它的一般形式为:
                        fseek(文件指针,位移量,起始点);
    在文件操作中可能需要从文件中的某个位置开始进行读写,此时可以使用 fseek 函数将位置指针移动到指定位置,实现随机读写
    位移量是以“起始点”为基准移动的字节数( long
    +” 表示向后移动
    -” 表示向前移动。

    例如:
    fs eek(fp,40L,0);  
      // 将位置指针移动到文档开始后 40 个字节的位置
    fseek(fp,30L,1); 
      // 将位置指针移动到当前位置后 30 个字节的位置
    fseek(fp,-20L,2); 
      // 将位置指针移 动到文档末尾前 20 个字节的位置

    13.11】将指定字符串数据写入文本文件file_data.txt中,并将文件的位置指针定位到第5个字符之后,读出第6个字符并显示在屏幕上。

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    FILE *fp; 
    5.     char s[]="abcdefghijklmnopqrstuvwxyz";
    6.     char c;
    7.     if( (fp = fopen("file_data.txt","w+")) == NULL )
    8.     {    printf("can not open the file\n");
    9.         exit(0);
    10.     }
    11.     fprintf(fp,"%s",s);
    12.     fseek(fp,5L,0);
    13.     fscanf(fp,"%c",&c);
    14.     printf("The first character is: %c\n",c);
    15.     fclose(fp);
    16. }

     ftell函数

    ftell 函数的作用是返回文件位置指针的位置,给出当前位置指针相对于文件头的字节数,返回值为 long 型。当函数调用出错时,函数返回 -1L
    一般形式为
                    ftell(文件指针);

    13.12】求出文件中包含的字节数。

    分析:

    先将文件的位置指针移到文件末尾,再通过返回位置指针的位置来取得文件的字节数。

    1. #include
    2. #include
    3. void main()
    4. {    FILE *fp;
    5.     long l;
    6.     if( (fp = fopen("file_data.txt","r")) == NULL )
    7.     {    printf("can not open the file\n");
    8.         exit(0);
    9.     }
    10.     fseek(fp,0L,SEEK_END);   //将文件的位置指针移到文件末尾
    11.     l=ftell(fp);        //返回位置指针的位置
    12.     fclose(fp);
    13.     printf("the length of file is %ld\n",l);
    14. }

     feof函数

    feof 函数的作用是判断文件指针是否在文件末尾,如果在文件末尾,则返回非 0 ,否则返回 0
    一般形式为
                       feof(文件指针);

    13.13】判断文件指针是否在文本文件file_data.txt的末尾,并给出相应提示。

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    FILE *fp;
    5.     char ch;
    6.     if( (fp = fopen("file_data.txt","r")) == NULL )
    7.     {    printf("can not open the file\n");
    8.         exit(0);
    9.     }
    10.     do
    11.     {    ch=fgetc(fp);
    12.         putchar(ch);
    13.     }while (!feof(fp));   //判断是否到达文件尾
    14.     if(feof(fp)) printf("\nWe have reached end-of-file\n");
    15. //判断是否到达文件尾
    16.     fclose(fp);
    17. }

    ferror函数

    ferror 函数的作用是检查文件中是否有错误,如果有错,则返回非 0 ,否则返回 0
    它的一般形式为
    ferror(文件指针);

    13.14】判断的文本文件file_data.txt是否有错误,并给出相应提示。

    编写程序如下:

    1. #include
    2. #include
    3. void main()
    4. {    FILE *fp;
    5.     if( (fp = fopen("file_data.txt","r")) == NULL )
    6.     {    printf("can not open the file\n");
    7.         exit(0);
    8.     }
    9.     if(ferror(fp))
    10.         printf("Error reading from file_data.txt\n");
    11.     else
    12.         printf("There is no error\n");
    13.     fclose(fp);
    14. }

  • 相关阅读:
    数据结构历年考研真题对应知识点(栈)
    突破亚马逊智能检测,全自动化运营的新利器:亚马逊鲲鹏系统
    iClient for MapboxGL对接WMS服务
    在SpringBoot项目中整合SpringSession,基于Redis实现对Session的管理和事件监听
    技术分享 | 开发板网口热插拔自动获取IP地址
    thinkPHP基于php的衡水游泳馆管理系统-计算机毕业设计
    Redis 主从搭建和哨兵搭建
    企业如何结合 SaaS 与 RADIUS 保障 WiFi 安全?
    驱动开发--自动创建节点udev机制的实现过程分析
    Mysql命令行常用基本操作
  • 原文地址:https://blog.csdn.net/m0_64148419/article/details/140241989