第十一章 文件概述

文件概念

从文件编码方式的分类,文件可以分为ASCII码文件和二进制文件两类。

  ASCII码文件(又称文本文件)的每一个字节存放一个ASCII码,代表一个字符,便于字符的输入和输出处理,但占用存储空间较大。

  二进制文件是把数据按其中在内存中的存储形式原样输出到磁盘上存放,一个字节并不对应一个字符,但占用存储空间较少。

  在C语言中,每一个打开的文件都对应一个特殊的指针并通过该指针对文件进行各种操作,这个指针称为文件指针。每个C程序,运行时系统必须至少提供三个流,标准输入(sdtin)、标准输出(stdout)和标准错误(stderr)它们都是一个指向FILE结构的指针。

在打开一个文件前,首先要定义一个文件类型的指针变量,用它指向这个打开的文件。定义文件指针变量的一般形式为:

  FILE *指针变量名(标识符)

文件的打开

  fopen函数打开一个特定的文件,并把一个流和文件相关联。它的原型如下所示:

  FILE *fopen(char const *name,char const *mode);

两个参数都是字符串。name是你希望打开文件或设备的名字。mode(模式)参数提示流是用来只读、只写还是既读又写,以及它是文本流还是二进制流。下面表格列出了一些常用的模式。

  读 取 写 入 添 加 读和写
文本 "r" "w" "a" "r+"、"w+"、"a+"
二进制 "rb" "wb" "ab" "rb+"、"wb+"、"ab+""

  mode以r、w或a开头,分别表示打开的流用于读取、写入还是添加。

注意:

  1)用"r"打开一个文件时,该文件必须已经存在,且只能从该文件读取。

  2)用"w"打开的文件只能向该文件写入。若打开的文件不存在,则以指定的文件名建立该文件;若打开的文件已存在,则将该文件清空,重新建一个新文件。

  3)如果向一个已存在的文件追加新的消息,只能用"a"方式打开文件。但此时该文件必须是存在的,否则将会出错。

如果fopen函数执行成功,它将返回一个指向FILE结构的指针。如果fopen函数执行失败,它将返回一个NULL值。

    FILE *input;
    input = fopen("data", "r");
    if (NULL == input) {
        perror("data");
        getch();
        exit(EXIT_FAILURE);
    }

  perror函数以一种简单、统一的方式报告错误。perror函数简化向用户报告这些特定错误的过程。原型定义于stdio.h,如下所示:

    void perror(char const *message);

如果message不是NULL并且指向一个非空字符串,perror函数就打印出这个字符串,后面跟一个分号和一个空格,然后打印出一条用于解释error当前错误代码的信息。

  exit函数用于终止一个程序的执行。原型定义于stdlib.h,如下所示:

    void exit(int status);

status参数返回给操作系统,用于提示程序是否正常完成。这个只和main函数返回的整型状态值相同。预定义符号EXIT_SUCCESS和EXIT_FAILURE分别提示程序的终止是成功还是失败。exit( )0表示程序正常退出,非0出错后退出,一闪而过。

getch()是编程中所用的函数,这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车。在这里该命令的作用是等待,只有当用户从键盘敲任意键时,程序才继续执行。

文件的关闭

  使用文件完毕,要释放文件缓冲区,避免文件中的数据的丢失,就应调用fclose函数关闭文件。它的原型如下:

    int fclose(FILE *fp);

对于输出流,fclose函数在文件关闭前刷新缓冲区。如果它执行成功,fclose返回零值,否则返回EOF(非零值)。

字符读写函数

  字符读写函数处理文本文件(文本流),文本流是字符序列,字符读写函数以字节为单位,其调用格式为:

    int fputc(int c,FILE *fp);

    int fgetc(FILE *fp);

  fputc将字符c写入文件指针fp指向的文件的当前位置。若成功则返回c,否则返回EOF(-1)。

  fgetc从文件指针fp指向的文件的当前位置读取一个字符作为函数值返回。

无论是执行读取或写入,文件指针fp会自动后移一个字节,以便进行下一次读写操作。

如果fputc的指针形参fp对应实参是stdout,那么实际效果就是向显示器中写入一个字符,其作用等效于putchar(c)。

如果fgetc的指针形参fp对应实参是stdin,那么实际效果就是从键盘中读入一个字符,其作用等效于getchar(c)。

字符串读写函数

  字符串读写函数处理文本文件(文本流),以串(按行)读写,函数原型为:  

    int fputs(char *s,FILE *fp);

    int fgets(char *s,int n,FILE *fp);

  fputs将字符串s舍去结束符''之后写入fp指向文件的当前读写位置,错误时返回EOF(-1),否则返回一个非负数。

  fgets从fp指向文件当前位置开始,最多读取n - 1个字符,末尾加'',具体分以下几种情况:

1)在遇到回车符或文件结束符之前,已经读取 n - 1个字符,则读取结束,加上串结束符''组成字符串,存入s指向的内存区。

2)若提取遇到换行符,则读取结束,在换行符之后加上串结束符''组成字符串。换行符是被读取的字符。

3)若提前遇到文件结束符,则读取结束,将文件结束符转换为串结束符''组成字符串。

4)若读取正常结束,则返回是字符串指针s,否则返回空指针NULL。

无格式读写数据函数

  无格式读写也称为按数据块读写,主要用于处理二进制文件。二进制流是字符序列,将字节序列分段截取,每一段代表一个数据元素,函数原型如下:

    int fwrite(void *buffer,int size,int n,FILE *fp);

    int fread(void *buffer,int size,int n,FILE *fp);

fwrite从程序数据区地址buffer开始,将连续size个字节的内容作为一个字段,一共n个字段写入fp指向的缓冲区,返回值是实际写入的数据块个数。

fread从fp指向的缓冲区,将连续size个字节的内容作为一个字段,一共n个字段写入buffer指向的程序数据区,返回值为实际读到的字符串个数。

格式读写函数

  标准输入输出函数scanf和printf实际上就是在键盘文件(stdin)和显示器文件(stdout)上的读写,将键盘文件指针(stdin)和显示器文件指针(stdout)替换为磁盘文件指针,就得到磁盘文件的格式读写。磁盘文件格式读写用到两个函数,原型如下:

    int fscanf(FILE *fp,const char *form,add1,add2……);

该函数从fp指向的缓冲区读取数据给相应的变量。遇到空格和换行符结束。其它参数和返回值和scanf函数一样。

    int fprintf(FILE *fp,const char *form,outputdata1,outputdata2……);

该函数向fp指向的缓冲区写入数据,其它参数和返回值和printf函数一样。

文件刷新函数

    刷新函数fflush,它迫使一个输出流的缓冲区内的数据进行物理写入,不管它是不是已经写满。原型如下:

    int fflush(FILE *stream);

当我们需要立即把输出缓冲区的数据进行物理写入时,应该使用这个函数。例如,调用fflush函数保证调试信息实际打印出来,而不是保存在缓冲区中直到以后才打印。

文件随机定位函数

  在正常情况下,数据以线性的方式写入,这意味着后面写入的数据在文件中的位置是在以前所有写入数据的后面。C同时支持随机访问I/O,也就是以任意顺序访问文件的不同位置。随机访问是通过在读取或写入先前定位到文件中需要的位置来实现的。

    long ftell(FILE *stream);

ftell函数返回流的当前位置。也就是说,下一个读取或写入将要开始的位置距离文件起始位置的偏移量。在二进制流中,这个值就是当前位置距离文件起始位置之间的字节数。

在文本流中,这个值表示一个位置,但它并不一定准确地表示当前位置和文件起始位置之间的字符数,因为有些系统将对行末字符进行翻译转换。但是ftell函数的返回值总是可以用于fseek函数中,作为一个距离文件起始位置的偏移量。

    int fseek(FILE *stream,long offset,int from):

fseek函数允许你在一个流中定位。将fp指向的文件内部位置指针从from起始位置移动offset指定的字节数,指向新的位置。这一操作将改变下一个读取或写入操作的位置。

其中offset为正数,表示向文件尾移动;0表示回到起始位置;负数表示向文件头移动。from为0(字符常量为SEEK_SET)表示起始位置是文件头;from为1(字符常量为SEEK_CUR)表示起始位置为当前位置;from为2(SEEK_END)表示起始位置是文件尾。

  1)offset如果是常数,则必须是长整型,为此整数后面要加'L'或'l'。如果是表达式,可以通过(long)(表达式)强制类型转换为长整型。

  2)fseek函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时往往会发生混乱。

文件头定位函数

  rewind函数将读/写指针设置回指定流的起始位置(文件头)。它同时清除流的错误提示标志。函数原型如下:

    int rewind(FILE *fp);

出错检测函数

  该函数用于测试fp指向的文件最后一次操作(读写、定位等)是否出错。无错,返回0值,有错,返回非0值。该函数原型如下:

    int ferror(FILE *fp);

文件尾测试函数

  该函数用于测试文件内部指针是否已到文件尾。如果是文件尾(文件结束)(真),返回非0;否则返回0,该函数原型如下:

    int feof(FILE *fp);

文件标志复位函数

  该函数用于清除出错标志和文件结束标志,即置feof和ferror函数值为0。该函数原型如下:

    void clearerr(FILE *fp);

文件操作函数

有两个函数用于操作文件但不执行任何输入/输出操作。它们原型如下所示。如果执行成功,这两个函数都返回零值。如果失败,它们都返回非零值。

    int remove(char const *filename);

    int rename(char const *oldname,char const *newname);

remove函数删除一个指定的文件。如果当remove被调用时文件处于打开状态,其结果则取决于编译器。

rename函数用于改变一个文件的名字,从oldname改为newname。如果已经有一个名为newname的文件存在,其结果取决于编译器。如果这个函数失败,文件仍然可以使用原来的名字进行访问。

原文地址:https://www.cnblogs.com/Yang-Xin-Yi/p/13636598.html