一直想着把C语言和C++关于文件操作的相关内容总结一下,这样在使用的时候就可以顺手拈来,嗯,这就是好记性不如烂笔头。既然是文件操作,那么开篇就从“文件”的介绍开始。
1、文件
文件指存储在外部介质上的相关数据的集合。存放文件的外部介质有磁带、磁盘、光盘等外部存储器。数据包括:数字、文字、图形、图象、声音、视频等。每个文件都有一个名字,叫做文件名。计算机操作系统就是根据文件名对各种文件进行存取和处理的。
输入输出可以使屏幕等(标准输出文件指针:stdout)为输出设备,以键盘(标准输入文件指针:stdin)为输入设备。而程序运行有时需要把数据存放到磁盘中,从磁盘中输入最后在输出到磁盘上,这就要用到磁盘文件。文件的输入输出时是这里介绍的重点。
1.1文件的分类
(1)文件按存放设备可分为磁盘文件和设备文件两种。
磁盘文件:存放在磁盘上的数据文件,包括硬盘和软盘等等。
设备文件:操作系统与外部设备(例如,磁带驱动器,磁盘驱动器,打印机,终端,modern)是通过一种被称为设备文件的文件来进行通信。UNIX输入输出到外部设备的方式和输入输出到一个文件的方式是相同的。在UNIX 同一个外部设备进行通讯之前,这个设备必须首先要有一个设备文件存在。例如,每一个终端都有自己的设备文件来供UNIX写数据(出现在终端屏幕上),和读取数据(用户通过键盘输入)。
设备文件和普通文件不一样,设备文件中并不包含任何数据。操作系统通过设备文件来与一个设备进行通讯。设备文件存在于/dev目录下。由于UNIX操作系统为你创建所有的设备文件,所以在你存取一个外部设备的时 候,你需要知道这个设备对应的设备文件名。有时候你会需要自己创建一个设备文件。如果你永久地去掉一个外部设备,你应该删除它对应的设备文件。
(2)文件按数据的组织形式又可分为ASCII码文件(或称文本文件)和二进制文件两种。
ASCII文件(或称文本文件):ASCII码文件可在屏幕上按字符显示,此种存储形式便于输出显示。以ASCII码或者其他文字语言的交换编码存储的文件,可以直接在屏幕或者打印机输出为人们识别的信息。ASCII文件在磁盘中存放时,每个字符对应一个字节,用于存放对应的ASCII码。如:整型十进制数12345,按ASCII文件存放则需要占用5个字节。可在屏幕上显示,但占用空间较大,读写操作要转换。
ASCII码文件特点:存储量大、速度慢、便于对字符操作
二进制文件:二进制文件是按二进制的编码方式来存放文件的。二进制文件中的数据与该数据的二进制形式是一致的。即对不同的数据类型,按其实际占用内存字节数存放,与其在内存的存储形式相同,原样输出到磁盘上存放。如:整型十进制数12345,按二进制文件存放只需要2个字节。屏幕显示为乱码,但占用空间小,读写操作效率高。
二进制文件特点:存储量小、速度快、适于存放中间结果。
不同的文件格式文件的存储方式是不同的,我们都应该注意加以区分,因为无论是通常的使用还是编程都是至关重要的,例如:
*.C C语言的源程序 ASCII码文件
*.OBJ 目标文件 二进制文件
*.EXE 可执行文件 二进制文件
(3) 按读写方式文件可分为顺序文件和随机文件。
对顺序文件来说,读写必须从头开始。对随机文件来说,读写的过程是随机的。
2、C语言文件操作
要了解Linux C文件的处理方式首先要了解流(Stream)的概念。C语言把文件看作是一个字符(字节)的序列,即由一个一个的字符或字节的数据顺序组成。换句话说,C语言是把每一个文件都看作是一个有序的字节流。
流是文件和程序之间的通道。一个C程序可以创建文件和对文件内容进行更新、修改,在程序中所需的数据也可以从另一个文件中获得。
流是程序输入或输出的一个连续的数据序列,常用设备(如键盘、显示器和打印机等)的输入/输出都是通过流来处理的。在C语言中,所有的流均以文件的形式出现,包括设备文件。流实际上是文件输入/输出的一种动态形式,C文件就是一个字节流或二进制流。流作为连续数据序列不是由记录组成的。C文件输入/输出的字节流或二进制流仅受程序控制而不受物理符号(如回车换行符)控制。也就是说,文件输入/输出时不会考虑记录的界限,这种文件通常可以称为流文件。
C中有两种处理文件的方法:一种是“缓冲文件系统”;另一种是“非缓冲文件系统”。
缓冲文件系统又称为标准文件系统或高层文件系统,它与具体机器无关,通用性好,功能强,使用方便。系统自动地在内存区为每个正在使用的文件开辟一个缓冲区,文件的存取都是通过缓冲区进行的。缓冲区相当于一个中转站,它的大小由具体的C版本规定,一般为512字节。当从内存向磁盘输出数据时,先将数据送到内存缓冲区,待缓冲区装满后,再一起送到磁盘文件保存;当从磁盘文件读入数据时,则一次从磁盘文件中将一批数据输入到内存缓冲区,然后再从缓冲区逐个地将数据送到程序数据区。如图所示。
非缓冲文件系统又称为低层文件系统与机器有关,使用较为困难但节省内存,执行效率较高。系统不自动开辟一个内存缓冲区,而由用户根据所处理数据量的大小在程序中设置数据缓冲区。
缓冲文件系统原来用于处理文本文件,而非缓冲文件系统原来用于处理二进制文件。ANSI C不再采用非缓冲文件系统,而只采用缓冲文件系统,在处理二进制文件时,也通过缓冲文件系统进行。ANSI C通过扩充缓冲文件系统,使缓冲文件系统既能处理文本文件,又能处理二进制文件。但是我们在学习Linux C编程时不仅要重点学习ANSIC标准的文件处理方法,同样要学习Linux系统自身所有所有的文件与设备处理方法。因为非缓冲I/O是系统直接的输入和输出,它不经过“缓冲区”,所以从速度和效率方面来说就显得快一些了。在某些要求效率的特定情况下我们可能需要这一特性。
通常我们所操作的都是缓冲文件,因此本文章仅针对缓冲文件进行阐述。
3、文件类型指针和文件描述符
在缓冲文件系统(高级I/O系统)通过文件指针访问文件,而非缓冲文件系统 (低级磁盘I/O系统)则没有文件型指针,不是靠文件指针来访问文件,而是用一个整数代表一个文件(相当于 FORTRAN 等语言的 “文件号” ),这个整数称为“文件说明符”。下面我们将分别学习文件指针与文件说明符的概念及使用方法。
文件类型指针
文件类型指针是相对于缓冲文件系统的概念。在缓冲文件系统中,系统为每个被使用的文件都在内存中开辟一个区域,用来存放文件名、文件状态、缓冲区状态及文件当前位置等信息,这些信息被C语言系统保存在一个称作FILE的结构体中,它在stdio.h头文件中定义内。FILE结构体的内容为(在使用文件操作时,一般不用关心FILE内部成员信息):
typedef struct
{
shortlevel; /*缓冲区“满”或者“空”的程度*/
unsignedflags; /*文件状态标志*/
charfd; /*文件描述符*/
unsignedchar hold; /*如果无缓冲区则不读取字符*/
shortbsize; /*缓冲区的大小*/
unsignedchar*buffer; /*数据缓冲区的位置*/
unsignedchar*curp; /*指针,当前的指向*/
unsignedistemp; /*临时文件指示器*/
shorttoken; /*用于有效性检查*/
} FILE;
对于每一个要操作的文件,都必须定义一个指针变量,并使它指向该文件结构体变量,这个指针称为文件指针。通过文件指针找到被操作文件的描述信息,就可对它所指的文件进行各种操作。定义文件指针的一般形式为:
FILE* 指针变量标识符;
如:FILE *fp; 表示fp是一个指向FILE类型结构体的指针变量。可以使fp指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问该文件。
FILE是用typedef声明的文件信息结构体的别名,由C系统定义,用户只能使用,不能修改,并且FILE必须大写。
对文件的操作一般步骤包括:声明一个文件指针、通过文件名打开文件、为文件指针赋值、通过文件指针对文件进行存取、通过文件指针关闭文件。
*注:本文章部分内容来自《Linux C程序设计基础》,转载请注明出处。
我们团队有着十几年的期货程序化交易算法与软件研发经验,基于C++ Qt技术研发了具有自主知识产权的期货智能程序化交易一体化系统平台,该平台封装了二百多个量化指标,具有低时延、高性能、小滑点、可定制和跨平台的特点。团队致力于将人工智能技术与传统的程序化交易技术相结合为客户提供灵活可定制的期货智能程序化交易服务和产品。
2012年9月18日于北京邮电大学学八楼629