zoukankan      html  css  js  c++  java
  • 17.3.15---C语言详解FILE文件操作

                FILE 是 C语言文件结构定义, 打开文件和文件操作要用到这类结构。可以看成变量类型,用于变量声明。这个是一种数据结构类型,用来表示一个文件的相关信息,如果定义了一个文件指针,就用这个指针来指向某个文件,然后就能使用这个指针对文件来进行操作了。

          FILE在"stdio.h"中有如下定义:

     1 struct _iobuf {
     2 char *_ptr; //文件输入的下一个位置
     3 int _cnt; //当前缓冲区的相对位置
     4 char *_base; //指基础位置(即是文件的其始位置)
     5 int _flag; //文件标志
     6 int _file; //文件的有效性验证
     7 int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
     8 int _bufsiz; //文件的大小
     9 char *_tmpfname; //临时文件名
    10 };
    11 typedef struct _iobuf FILE;
     程序运行时  FILE变量已经被加载到了内存中  这里一般不说缓冲区
     当你需要打开一个文件操作时   第一步肯定是访问FILE结构体  获取文件内容实际的地址

    这个时候 系统根据FILE存储的实际地址 找到文件的真实内容所在 然后把它文件加载到内存中 也称为缓存中

    记住FILE只是存储了文件的指针就行了

     这个是关键
     

     ---

     变量里面存着文件的地址------>由这个地址在磁盘找到文件的位置--->然后把该位置下的内容复制到缓冲区(在满足一定条件下)----->进行读取
    ---------

    1----需要了解的概念:

          数据流,缓冲区,文件类型,文件存取方式

    2---概念解释:

          数据流:指程序与数据的交互是以流的形式进行的。进行C语言文件的存取时,都会先进行“打开文件”操作,这个操作就是在打开数据流,而“关闭文件”操作

    就是关闭数据流。

          缓冲区(Buffer):指在程序执行时,所提供的额外内存,可用来暂时存放做准备执行的数据。它的设置是为了提高存取效率,因为内存的存取速度比磁盘驱

    动器快得多。

    、3--- C语言中带缓冲区的文件处理:

          C语言的文件处理功能依据系统是否设置“缓冲区”分为两种:一种是设置缓冲区,另一种是不设置缓冲区。由于不设置缓冲区的文件处理方式,必须使用较低级的I/O函数(包含在头文件io.h和fcntl.h中)来直接对磁盘存取,这种方式的存取速度慢,并且由于不是C的标准函数,跨平台操作时容易出问题。

          

    下面只介绍第一种处理方式,即设置缓冲区的文件处理方式:

    当使用标准I/O函数(包含在头文件stdio.h中)时,系统会自动设置缓冲区,并通过数据流来读写文件。当进行文件读取时,不会直接对磁盘进行读取,而是先打开数据流,将磁盘上的文件信息拷贝到缓冲区内,然后程序再从缓冲区中读取所需数据,如下图所示:

     

    事实上,当写入文件时,并不会马上写入磁盘中,而是先写入缓冲区,只有在缓冲区已满或“关闭文件”时,才会将数据写入磁盘,如下图所示。

    4--- 文件类型:

    分为文本文件和二进制文件两种。

    文本文件是以字符编码的方式进行保存的。二进制文件将内存中数据原封不至文件中,适用于非字符为主的数据。如果以记事本打开,只会看到一堆乱码。

    其实,除了文本文件外,所有的数据都可以算是二进制文件。二进制文件的优点在于存取速度快,占用空间小,以及可随机存取数据。

    5-- 文件存取方式:

    包括顺序存取方式和随机存取方式两种

    顺序读取也就是从上往下,一笔一笔读取文件的内容。保存数据时,将数据附加在文件的末尾。这种存取方式常用于文本文件,而被存取的文件则称为顺序文件。

    随机存取方式多半以二进制文件为主。它会以一个完整的单位来进行数据的读取和写入,通常以结构为单位。

    6--. 文本文件操作

    C语言中主要通过标准I/O函数来对文本文件进行处理。相关的操作包括打开、读写、关闭与设置缓冲区。
    相关的存取函数有:fopen(), fclose(), fgetc(), fputc(), fgets(), fputs(), fprintf(), fscanf()等。

        1)打开文件--

              

                函数原型为:_CRTIMP FILE * __cdecl fopen(const char *, const char *);

                第一参数为文件名,第二个参数为打开模式。

                打开成功,fopen返回一个结构指针地址,否则返回一个NULL。如果没有指定文件路径,则默认为当前工作目录。如:

    1 FILE *fp;
    2 fp = fopen("c:\temp\test.txt", "r") //由于反斜杠是控制字符,所以必须再加一个反斜杠

                                      使用fopen()函数打开的文件会先将文件复制到缓冲区

               注意:所下达的读取或写入动作,都是针对缓冲区进行存取而不是磁盘,只有当使用fclose()函数关闭文件时,缓冲区中的数据才会写入磁盘。

        谈文件打开模式  

      打开文本文件:

    "r":只能从文件中读数据,该文件必须先存在,否则打开失败
    "w":只能向文件写数据,若指定的文件不存在则创建它,如果存在则先删除它再重建一个新文件
    "a":向文件增加新数据(不删除原有数据),若文件不存在则打开失败,打开时位置指针移到文件末尾
    "r+":可读/写数据,该文件必须先存在,否则打开失败
    "w+":可读/写数据,用该模式打开新建一个文件,先向该文件写数据,然后可读取该文件中的数据
    "a+":可读/写数据,原来的文件不被删去,位置指针移到文件末尾

    打开二进制文件的模式与打开文本文件的含义是一样的,不同的是模式名称里面多一个字母'b’,以表示以二进制形式打开文件。

          2)关闭文件

              函数原型为:_CRTIMP int __cdecl fclose(FILE *);

                  关闭成功返回值0,否则返回非零值。

               注:在执行完文件的操作后,要进行“关闭文件”操作。虽然程序在结束前会自动关闭所有的打开文件,但文件打开过多会导致系统运行缓慢,这

                  时就要自行手动关闭不再使用的文件,来提高系统整体的执行效率。

     1 FILE *fp;
     2 fp = fopen("c:\temp\test.txt", "r");
     3 
     4 if(fp == NULL)
     5     printf("fail to open the file! 
    ");
     6 else
     7 {
     8     printf("The file is open! 
    ");
     9     fclose(fp);
    10 }

          3)字符存取函数

            函数原型为:_CRTIMP int __cdecl fputc(int, FILE *);
                  _CRTIMP int __cdecl fgetc(FILE *);

    字符读取函数fgetc()可从文件数据流中一次读取一个字符,然后读取光标移动到下一个字符,并逐步将文件的内容读出。

    如果字符读取成功,则返回所读取的字符,否则返回EOF(end of file)。EOF是表示数据结尾的常量,真值为-1。另外,要判断文件是否读取完毕,可利用feof()进行检查。未完返回0,已完返回非零值。

                feof()函数原型为:_CRTIMP int __cdecl feof(FILE *);

    ---------> fgetc()函数的使用

                                                   利用feof()函数检查文件是否读取完毕

     1 #include <stdio.h>
     2 
     3 main()
     4 {
     5     FILE *fp;
     6     fp = fopen("c:\temp\test.txt", "r");
     7     if(fp != NULL)
     8     {
     9         while(!feof(fp))
    10             printf("%c", fgetc(fp));
    11     }
    12     else
    13         printf("fail to open! 
    ");
    14     fclose(fp);
    15 
    16     return 0;
    17 }

    或者可以这样:利用文件结束标志EOF(即-1)

     1 #include <stdio.h>
     2 
     3 main()
     4 {
     5     char ch;
     6     FILE *fp;
     7     fp = fopen("c:\temp\test.txt", "r");
     8     if(fp != NULL)
     9     {
    10         ch = fgetc(fp);
    11         while(ch != EOF)
    12         {
    13             putchar(ch);
    14             ch = fgetc(fp);
    15         }
    16 
    17     }
    18     else
    19         printf("fail to open! 
    ");
    20     fclose(fp);
    21 
    22     return 0;
    23 }

    若要将字符逐一写入文件,用fputc()函数。示例为:

                fputc()函数的使用

     1 #include <stdio.h>
     2 #include <conio.h>
     3 
     4 main()
     5 {
     6     char filename[20], ch;
     7     FILE *fp;
     8     printf("Enter a filename: ");
     9     scanf("%s", filename);
    10     printf("Enter some characters to output to file: ");
    11     if((fp = fopen(filename, "w")) == NULL)
    12         printf("fail to open! 
    ");
    13     else
    14     {
    15         while((ch = getche()) != '15')
    16             fputc(ch, fp);
    17     }
    18     fclose(fp);
    19 
    20     return 0;
    21 }

           4)字符串存取函数

    函数原型为:

    _CRTIMP int __cdecl fputs(const char *, FILE *);
    _CRTIMP char * __cdecl fgets(char *, int, FILE *);

    fgets函数的作用是从指定文件读入一个字符串,如:fgets(str, n, fp);

    参数n为要求得到的字符个数,但只从fp指向的文件输入n-1个字符,然后在最后加一个''字符,因此得到的字符串共有n个字符,把它们放在字符数组str中。如果在读完n-1个字符之前遇到换行符或EOF,读入结束。

    fputs函数的作用是向指定文件输出一个字符串,如:fputs("Hey", fp);

    把字符串"Hey"输出到fp指向的文件。fputs函数的第一个参数可以是字符串常量、字符数组名或字符型指针。若输出成功,则返回0,否则返回EOF。

          5)格式化存取函数

    函数原型为:

    _CRTIMP int __cdecl fprintf(FILE *, const char *, ...);
    _CRTIMP int __cdecl fscanf(FILE *, const char *, ...);

    它们与printf和scanf函数相仿,都是格式化读写函数。不同的是:fprintf和fscanf函数的读写对象不是终端(标准输入输出),而是磁盘文件。printf函数是将内容输出到终端(屏幕),因此,fprintf就是将内容输出到磁盘文件了。

    fprintf和fscanf函数的使用

     1 #include <stdio.h>
     2 
     3 void main()
     4 {
     5     FILE *fp;
     6 
     7     int num = 10;
     8     char name[10] = "Leeming";
     9     char gender = 'M';
    10 
    11     if((fp = fopen("info.txt", "w+")) == NULL)
    12         printf("can't open the file! 
    ");
    13     else
    14         fprintf(fp, "%d, %s, %c", num, name, gender); //将数据格式化输出到文件info.txt中
    15 
    16     fscanf(fp, "%d, %s, %c", &num, name, &gender); //从文件info.txt中格式化读取数据
    17     printf("%d, %s, %c 
    ", num, name, gender); //格式化输出到屏幕
    18 
    19     fclose(fp);
    20 }
  • 相关阅读:
    postgre通过sql释放空闲连接
    LeetCode Weekly Contest 255
    响应式编程基础教程:Spring Boot 与 Lettuce 整合
    响应式编程基础教程:Spring Boot 与 R2DBC 整合
    Spring WebFlux 基础教程:WebSocket 使用
    Spring WebFlux 基础教程:参数校验
    Spring WebFlux 基础教程:快速入门
    LeetCode | 46. 全排列
    LeetCode | 买卖股票的最佳时机
    LeetCode | 动态规划_小青蛙跳楼梯
  • 原文地址:https://www.cnblogs.com/xiaoyoucai/p/6553494.html
Copyright © 2011-2022 走看看