文件是外存中管理数据的基本单位。外存中的数据可以长期保存,但是,存取效率低。缓冲文件系统可以提高数据的存取效率,不过,在程序中使用文件后,显式地关闭文件就成了“规定动作”。
外存像仓库,存储了大量的待加工、半加工和已加工的数据。内存像车间,存放着正加工的数据。由于文件中通常存储了大量的数据,它所包含的存储单元的类型可能非常复杂。文件中最小的存储单元也是字节。如果一个文件中包含了12个字节,那么它存储了什么样的数据呢?12个字符?一个int型整数和一个双精度型的小数?一个双精度型的小数和一个int型整数?“文件”也是有“类型的”,通常根据所包含存储单元的类型的规律把文件分为“文本文件”和“二进制文件”。文本文件的全部字节均为字符型;不是文本文件的文件就是二进制文件了,如常见的MP3文件,BMP文件等。二进制文件中存储单元的类型没有规律,使用时必须针对具体的类别(如MP3文件),研究其中的第几字节至第几字节是什么类型的。文件中都是由0和1组成的数字串,所以,文本文件也是“二进制”文件。
使用文件时既能以字节为单位一次存取一个字节,又能以块为单位一次存取n个字节。文件中有一个当前位置指针变量,指向要存取存储空间的首字节,它会根据用户实际存取的数据量自动调整指向位置,因此,在存取文件中数据时可以不必考虑相关存储空间的位置。
程序中处理数据时还是要利用变量,而每个变量都有具体的类型,因此,从文件中读取的数据要用匹配类型的变量存储。文件中数据类型的复杂性增加了程序中选择匹配变量的难度。
外存中的文件由操作系统负责管理,不同操作系统的文件系统可能有所区别,但是,操作系统大都将设备也抽象为文件。例如,将“键盘”抽象为一个文件,用户通过键盘输入的数据会保存在这个文件中,而程序获得用户输入数据时只是读取这个文件的内容。这个文件就是所谓的“输入缓冲区”。“输入设备”是一个文件(“输入文件”),而“输出设备”也是一个文件(“输出文件”),实际上在前面的程序中已经多次使用它们了。输入文件是一个文本文件,以字符串格式存储用户输入的数据,虽然用户觉得输入的是“整数”或“小数”。scanf函数读取输入文件的内容并根据格式字符把字符串型的数据重新“编码”为整型或浮点型,“编码”的过程可参见例6-16。输出文件也是一个文本文件,printf函数向其中写入字符型数据,输出设备上就会显示相应字符(字形码)。设保存处理结果的变量j的值为整数371,它实际的存储状态为二进制的00000000 00000000 00000001 01110011,如何用printf函数输出变量j的值呢?用格式字符x将其转换为字符串“173”,还是用格式字符d将其转换为字符串“371”?一个是真实的存储状态,一个是“看得明白”的值。程序中使用文件时遇到的问题与使用scanf函数和printf函数输入输出数据时遇到的类似。如何匹配文件中数据的类型和程序中变量的类型是本章的难点。
只要通过库函数指定了当前位置指针变量指向的位置,文件就可以随机读写了。
有了文件,程序的处理结果可以长期保存并方便地传阅了;有了文件,程序所需的输入数据不必由用户在程序运行时通过键盘输入了。