天天看点

C语言 ——文件处理(奇葩知识系列 )

1 引言

● 文件是用来永久地保存大批量数据的

● 计算机将文件存储在硬盘、固态盘、闪存盘和DVD盘这样的辅存上

2 文件与流

● 在C语言中,文件不过是一个按顺序组成的字节流。当一个文件被打开时,就会有一个流与这个文件联系在一起

● 当程序开始执行时有三个文件及其相联系的的流被自动打开——即标准输入、标准输出和标准错误

● 流提供了文件与程序之间的信息交流通道

● 标准输入流使得程序能够从键盘上读入数据而标准输出流使得程序能够将数据打印到屏幕上

● 每次打开一个文件都会返回一个指向FILE结构体类型(在头文件<stdio.h>中定义)的指针,FILE结构体类型中包含有处理这个文件有关的信息。这个结构体中包含有一个文件描述头,文件描述头就是针对所谓"打开文件列表"的一个操作系统数组的一个索引,数组的每一个元素包含有一个文件控制块(FCB),而操作系统就是通过FCB来管理一个特定的文件的

● 系统通过文件指针stdin,stdout和stderr来操纵标准输入、标准输出和标准错误这三个文件

● 函数fgetc从一个文件中读取一个字符。它接收一个指向目标文件的FILE指针作为实参

● 函数fputc向一个文件中写入一个字符。它接收一个欲写入该目标文件的字符和一个指向目标文件的文件指针作为实参

● 函数fgets和fputs分别用来从文件中读取一行和向文件中写入一行字符

3 顺序存取文件的创建

● C语言没有将结构体运用在文件之上。必须提供一个文件结构来满足某些应用的需求

● C程序用一个单独的FILE结构体来管理每个文件

● 每次打开一个文件,都需要一个单独声明的、类型为FILE的指针,用于实现对文件的引用

● 函数fopen需要两个实参:文件名和文件打开模式,函数的返回值是指向被打开文件的FILE结构体类型的指针

● 文件打开模式 w 表示文件是为写操作而打开的。若文件事先并不存在,则函数fopen创建该文件。若文件事先存在,则文件中原有的内容将会在不给出任何警告的情况下被全部丢弃

● 若无法打开一个文件,则函数fopen返回一个NULL值

● 函数feof接收一个指向FILE的指针。若文件结束标记已经被设置,则函数返回一个非零值(真),否则返回0

● 函数fprintf基本上是等价于函数printf的,只不过fprintf函数需要多接收一个文件指针作为实参,这个文件指针指向的文件就是数据将要被写入的目标文件

● 函数fclose接收一个文件指针作为实参并关闭该文件

● 当一个文件被打开时,它的文件控制块(FCB)就被复制到内存中。操作系统使用FCB来管理文件

● 若想创建一个新文件,或者想在写入新的数据之前丢弃一个已有文件中的全部内容则应该以写(“w”)模式来打开一个文件

● 若想读取一个已存在的文件,则应该以读(“r”)模式来打开该文件

● 若想在一个已存在的文件末尾添加记录,则应该以添加(“a”)模式来打开该文件

● 若想对文件既读又写,则可使用更新模式(“r +”,“w +”,“a +”)这三个中的一个来打开文件。

  1. 模式 r + :为了 读/写 而打开一个文件
  2. 模式 w + :为了 读/写 而创建一个文件,若文件已经存在那么以这种方式打开文件时,文件中当前的内容都会被丢弃。
  3. 模式 a + :为了 读/写 而打开一个文件但是所有的写操作必须在文件的末尾进行,若文件事先并不存在则创建该文件

    ● 每一个文件打开模式都有一个与其相对应的二进制模式(加上字母 b),这些模式都是用来处理二进制文件的

    ● C11还通过在模式 w,w+,wb,wb+的后边增加一个 x ,来提供互斥写模式

4 从顺序文件中读取数据

● 函数fscanf基本上是等价于函数scanf的,只不过fscanf函数需要多接收一个文件指针作为实参,这个文件指针指向的文件就是要从中读取数据的目标文件

● 为了从顺序存取文件中提取特定的数据,程序要从文件头开始连续地读取数据,直到发现欲提取的数据为止

● 函数rewind将程序的文件位置指针重新定位于其实参所指向的文件的开头(即字节编号为0)

● 文件位置指针是一个整数值,这个整数值表示文件中下一个 读/写 操作将发生在哪个字节位置上。文件位置指针也称为文件偏移量。文件位置指针是与每个文件相联系的FILE结构体中的一个成员

● 顺序文件中的数据在被修改时,会具有破坏文件中其他数据的风险

5 随机存取文件

● 随机存取文件中的记录一般是固定长度的,无须搜索其他记录,就能够直接访问这些记录(所以速度快)

● 由于随机存取文件中每一个记录的长度都是相同的,所以,每一个记录相对于文件开头的精确位置都可以根据基于记录键的线性函数计算出来

● 固定长度的记录,允许向一个随机存取文件中插入数据,而不会破坏其他数据。还可以对已经存入文件的数据进行更改或者删除,而无须重写整个文件

6 随机存取文件的创建

● 函数fwrite将从某个特定地址开始存储特定数目的字节数据,从内存中转移到一个文件中,而文件位置指针指示了文件中这些字节数据被写入的起始地址

● 函数fread将文件位置指针指示的地址开始存储的特定数目的字节数据,从一个文件中转移到某个特定地址开始的一个内存区域中

● 函数 fwrite 和 fread 具有将数据数组读出或写入文件的功能。函数中的第三个实参表示要处理的元素个数

● 文件处理程序通常都是一次写一个结构体

● 函数 fwrite 每次都是向文件中写入一个数据块(特定数目的字节)

● 为了向磁盘文件中写入某个数组中的若干个元素,在函数fwrite 调用语句中,需要将指向该数组的指针作为函数的第一个实参,将欲写入的元素的个数作为第三个实参

7 随机地向一个随机存取文件中写入数据

● 函数 fseek 将文件位置指针定位在文件中某个特定位置上。其中,第二个实参表示文件位置指针将要搜索经过的字节数,第三个实参表示文件位置指针开始搜索的位置。第三个实参有三个可选值:SEEK_SET 、SEEK_CUR 、SEEK_END (都在<stdio.h>中定义)

  1. SEEK_SET:表示搜索从文件的头部开始
  2. SEEK_CUR:表示搜索从文件的当前位置开始
  3. SEEK_END:表示偏移量从文件尾部开始计算

    ● 工业级应用程序应通过检查函数的返回值来判断诸如 fscanf ,fseek ,fwrite 这样的函数是否正确地执行了

    ● 函数 fscanf 返回成功读取的数据项的个数,若在读的过程中发生了问题,也返回EOF

    ● 当搜索操作无法进行时,函数fseek将返回一个非零值

    ● 函数fwrite 返回成功输出的数据项的个数。若返回值小于函数调用中的第三个实参,则说明发生了一个写错误

8 从一个随机存取文件中读取数据

● 函数 fread 将特定数目的字节从一个文件中读入内存

● 通过提供指向一个存储将要读来的数据的数组的指针以及欲读取元素的个数,fread 函数可以为该数组读取若干个固定长度的数组元素

● 函数 fread 返回成功输入的数据项的个数。若返回值小于函数调用中的第三个实参,则说明发生了一个读错误

继续阅读