文件管理的库函数介绍

文件基础知识

  • 程序设计中的文件

    • 程序文件:如源程序文件(.c)、目标文件(.obj)、可执行文件(.exe)等

    • 数据文件:程序运行需要从中读取、输出数据的文件

      注:数据文件大多被称为二进制文件,根据数据的组成,有的称为文本文件

  • 文件名

    • 概念:一个文件的唯一标识,以便用户识别和引用
    • 组成:文件路径 + 文件名主干 + 文件后缀
  • 文件类型

    • 数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件
    • 若要求在外存上以ASCLL码的形式存储,则需要在存储前进行转换。以ASCLL字符的形式存储的文件就是文本文件
  • 文件缓冲区(File Buffer)

    文件缓冲区

    • 工作原理

      • 当程序执行写操作(如 fwrite )时,数据不会立即写入磁盘,而是先存入缓冲区
      • 当缓冲区满、程序调用 fflush 强制刷新、或关闭文件( fclose )时,缓冲区中的数据才会一次性写入磁盘
      • 读操作(如 fread )时,系统会先从磁盘读取一批数据到缓冲区,再从缓冲区向内存传递数据
      • 缓冲区的大小根据C编译系统决定
    • 缓存区的作用

      • 减少对磁盘的直接读写次数(磁盘 IO 速度远慢于内存操作)
      • 提高文件操作效率,降低系统开销
    • 缓冲区的分类

      • 全缓冲:缓冲区满时才进行实际 IO 操作(默认对磁盘文件使用)
      • 行缓冲:遇到换行符\n或缓冲区满时刷新(通常用于终端设备)
      • 无缓冲:数据直接写入,不经过缓冲区(如 stderr 标准错误流)
    • 实例:文件缓冲区造成的显示错误

      linux系统中,死循环打印 “hehe” 并 sleep(1),屏幕上没有及时地显示信息

  • 文件指针(文件流)

    • 概念:缓冲文件系统中,使用文件指针统一了对不同设备(磁盘文件、终端、网络等)的操作接口

    • 流的类型:

      • 文本流:按字符序列处理,会自动转换换行符(如 Windows 下\n转换为\r\n)
      • 二进制流:按字节序列处理,数据原样传输,不做转换
    • 标准流:

      • stdin:标准输入流(通常对应键盘)

      • stdout:标准输出流(通常对应屏幕)

      • stderr:标准错误流(通常对应屏幕,用于输出错误信息)

      • 文件指针(文件流)与文件缓冲区的关系

        • 文件流是数据传输的逻辑通道,文件缓冲区是流操作的物理载体
        • 每个文件流都关联一个或多个缓冲区,所有 IO 操作都通过缓冲区间接完成
        • 关闭文件流(fclose)时会自动刷新其关联的缓冲区,确保数据完整性
      • 每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字、文件状态、文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体变量是有系统声明的,取名FILE。例如打开文件f1、f2、f3

    注:

    • 不同的C编译器对FILE类型包含的内容不完全相同,但大同小异
    • 每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构体变量,并填充其中的信息,使用者不必关系细节
    • 一般都是通过一个FILE指针来维护这个结构体变量,这样使用起来更加方便

文件操作(<stdio.h>)

文件的打开与关闭(fopen、fclose)

  • fopen

    • 函数原型:FILE *fopen( const char *filename, const char *mode );

    • 功能:以 mode 参数的格式打开文件,返回维护文件的 FILE* 指针

    • mode参数介绍

      文件使用方式(mode) 含义 如果指定文件不存在
      “r”(只读) 为了输入数据,打开一个已经存在的文本文件 出错
      “w”(只写) 为了输出数据,打开一个文本文件 建立一个新的文件
      “a”(追加) 向文本文件尾添加数据 建立一个新的文件
      “rb”(只读) 为了输入数据,打开一个二进制文件 出错
      “wb”(只写) 为了输出数据,打开一个二进制文件 建立一个新的文件
      “ab”(追加) 向一个二进制文件尾添加数据 出错
      “r+”(读写) 为了读和写,打开一个文本文件 出错
      “w+”(读写) 为了读和写,建立一个新的文件 建立一个新的文件
      “a+”(读写) 打开一个文件,在文件尾进行读写 建立一个新的文件
      “rb+”(读写) 为了读和写打开一个二进制文件 出错
      “wb+”(读写) 为了读和写,新建一个新的二进制文件 建立一个新的文件
      “ab+”(读写) 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件

      注:

      • filename可以写成相对路径,也能写成绝对路径,但要注意对 \ 进行转义
      • 除了追加模式、读模式等,其余都会覆盖掉原文件数据
      • 这里的读写的主语是此程序,宾语(对象)是文件指针指向的文件
      • 相对路径的表示方法
        • “./”表示当前路径
        • “../”表示上一路径,例如”../test.txt”
        • “…/”表示上一路径的上一路径,例如”…/test.txt”
  • fclose

    • 函数原型:int fclose( FILE *stream );
    • 功能:
      • 关闭一个已经打开的文件流(文件指针)
      • 确保所有缓冲数据(尚未写入文件的内容)被刷新到文件中
      • 释放系统为该文件分配的资源(如文件描述符)
      • 使文件指针不再指向该文件,避免后续误操作
    • 注意事项:
      • 使用结束后,需要将存放文件指针的变量赋为空指针

读写字符

  • fgetc(读取字符)

    • 函数原型:int fgetc(FILE *stream);
    • 功能:从指定的文件流中读取一个字符(以无符号字符形式转换为 int 类型返回),同时将文件内部指针向后移动一个位置。当读取到文件末尾或发生错误时,返回EOF(通常定义为 - 1)
  • fputc(写入字符)

    • 函数原型:int fputc(int ch, FILE *stream);
    • 功能:将参数ch指定的字符(取其低 8 位)写入到指定的文件流中,同时将文件内部指针向后移动一个位置。成功时返回写入的字符(转换为 int 类型),失败时返回EOF

    注:fgetc 返回 int 类型而非 char,是为了能区分正常字符(0-255 范围)和表示结束的 EOF(-1),避免因字符值为 0xFF(对应 - 1 的补码)而产生混淆

读写文本行

  • fgets(读取文本行)
    • 函数原型:char *fgets( char *str, int count, FILE *stream );
    • 功能:从指定流中读取最多num-1个字符(包含换行符)存入str指向的缓冲区,自动在末尾添加\0终止符。若读取到换行符或文件结束,会停止读取并返回str;失败或读到文件尾时返回NULL
  • fputs(写入文本行)
    • 函数原型:int fputs( const char *str, FILE *stream );
    • 功能:将str指向的字符串(不包含终止符\0)写入指定流,成功返回非负值,失败返回EOF

格式化文本读写

  • fscanf(格式化读取)
    • 函数原型:int fscanf( FILE *stream, const char *format, ... );
    • 功能:从指定流中按format格式读取数据,存入后续参数指向的变量。返回成功匹配并赋值的参数个数,失败或读到文件尾时返回EOF
  • fprintf(格式化写入)
    • 函数原型:int fprintf( FILE *stream, const char *format, ... );
    • 功能:按format格式将后续参数的数据写入指定流。返回成功写入的字符数,失败返回负值

二进制读写

  • fread(二进制读取)
    • 函数原型:size_t fread( void *ptr, size_t size, size_t count, FILE *stream );
    • 功能:从流中读取count个大小为size的字节块,存入ptr指向的内存。返回实际读取的完整块数(小于count可能表示出错或文件结束)
  • fwrite(二进制写入)
    • 函数原型:size_t fwrite( const void *ptr, size_t size, size_t count, FILE *stream );
    • 功能:将ptr指向的内存中count个大小为size的字节块写入流。返回实际写入的完整块数(若小于count表示写入失败)

fseek(设置文件指针位置)

  • 函数原型:int fseek(FILE *stream, long offset, int origin);
  • 功能:将文件流stream的位置指针移动到以origin为基准、偏移offset字节的位置
  • 注意事项:
    • origin取值:SEEK_SET(文件开头,值为 0)、SEEK_CUR(当前位置,值为 1)、SEEK_END(文件末尾,值为 2)
    • offset可正可负,正数表示向文件尾部方向移动,负数表示向文件头部方向移动
    • 对文本文件使用时,offset应为 0 或前次ftell返回的值,否则可能导致位置错误
    • 成功返回 0,失败返回非 0 值

ftell(获取文件指针位置)

  • 函数原型:long ftell(FILE *stream);
  • 功能:返回文件流stream当前位置指针相对于文件开头的偏移字节数
  • 注意事项:
    • 可用于计算文件长度(先定位到文件尾再调用)
    • 失败时返回 - 1L

rewind(重置文件指针到开头)

  • 函数原型:void rewind(FILE *stream);
  • 功能:将文件流stream的位置指针重置到文件开头,并清除文件流的错误标志
  • 注意事项:
    • 等价于fseek(stream, 0L, SEEK_SET);但无返回值
    • 同时会清除文件流的错误指示器

feof(检测文件结束)

  • 函数原型:int feof(FILE *stream);
  • 功能:检测文件流stream的位置指针是否已到达文件末尾
  • 注意事项:
    • 到达文件末尾时返回非 0 值(真),否则返回 0(假)
    • 仅在读取操作失败后使用才有意义,不能用于预测下一次读取是否成功
    • 区分文件结束和读错误需配合ferror函数使用
« 自定义数据类型 ← 返回列表 编译、预处理 »