




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第10章文件10.1文件概述和文件类型指针10.2文件的打开和关闭10.3文件的读/写10.4文件的定位10.5文件的检测10.6文件的综合示例本章小结
10.1文件概述和文件类型指针
10.1.1文件概述文件(file)是程序设计中一个重要的概念。在计算机系统中,“文件”是指存储在外部介质上的一组相关数据的有序集合。在前面章节中,我们采用标准输入(键盘输入)和标准输出(显示器输出)模式来处理数据信息。但大型程序常把外部介质(如磁盘)作为信息载体,用于长期存储输入和输出数据。
文件系统中,C语言将输入/输出设备当作文件,将输入/输出文件作为输入/输出流对象进行处理。输入/输出是数据“流动”的过程。当输入操作时,系统利用“读操作”使数据从文件流向计算机内存;当输出操作时,系统利用“写操作”使数据从计算机流向文件(如磁盘、打印机等)。
文件可以从不同的角度来进行分类:
(1)按文件所依附的介质分类,有卡片文件、纸带文件、磁带文件和磁盘文件等。
(2)按文件内容分类,有源文件、目标程序文件和数据文件等。
(3)按文件操作分类,有输入文件、输出文件和输入/输出文件。
(4)按文件中的数据组织形式分类,有字符文件和二进制文件。
字符文件又称为ASCII文件或文本文件,按字符方式存储,可用文本编辑器(如Windows系统中的记事本notepad.exe、写字板wordpad.exe等)进行直接读写,但所占存储空间较大;二进制文件是以二进制方式存储的,所占存储空间小,用文本编辑器不便进行直接读写。图10-1显示了十进制整数12345以字符文件存储和以二进制文件存储的区别。在C语言系统中,一个文件就是一个字符(字节)流。图10-1字符文件和二进制文件的存储区别
C语言文件系统有两种:缓冲文件系统(标准I/O)和非缓冲文件系统(系统I/O)。缓冲文件系统的特点是:系统在内存为正在使用的每一个文件开辟一个固定容量的“缓冲区”,当执行读操作时,先从磁盘上将指定的文件数据写入缓冲区,待缓冲区装满后再从缓冲区逐个将数据送到程序数据区;当执行写操作时,先将程序数据写入缓冲区,待缓冲区装满后再送到磁盘,如图10-2所示。
图10-2标准I/O读写文件操作示意图
由此可以看出,缓冲区越大,对外设访问的次数就越少,执行速度就越快、效率越高。一般来说,文件缓冲区的大小与编程环境有关,一般为512B。非缓冲文件,系统的特点是系统不会自动为正在使用的每一个文件开辟缓冲区,而由程序根据自身的需要及系统的存储资源情况来为每一个文件设定缓冲区。目前仍有许多C版本支持非缓冲文件系统,但1983年ANSIC标准决定不采用非缓冲区文件系统,因此这里建议读者不要采用不符合ANSIC标准的那些部分,以免降低程序的可移植性。
10.1.2文件类型指针
文件类型指针是缓冲文件系统中最重要的概念。对缓冲文件系统来说,ANSIC在内存中为每个被使用的文件开辟一小块固定大小的区域,用于存放文件的属性状态(如文件名、缓冲区的位置与大小等信息),该区域利用一个结构类型变量存放。该变量的结构类型是由系统定义的,取名为FILE,其定义包含在头文件stdio.h中,格式如下:
在C语言中,允许用类型FILE定义文件指针。每当要对某个文件进行操作时,应先定义一个FILE类型文件指针指向该文件,然后通过该文件指针对文件进行操作。文件指针的定义格式为
FILE*文件指针名;
例如:
FILE*fp;
定义了一个FILE类型的文件指针,指针名为fp。
10.2文件的打开和关闭
10.2.1文件的打开和其他高级语言一样,对文件进行读/写操作之前需要先“打开”该文件。所谓“打开”,是指为文件建立相应的信息区(用来存放文件的相关信息)和文件缓冲区,并建立文件与它们之间的联系。C语言提供了打开文件的函数fopen()。该函数原型在stdio.h头文件中,其调用格式为FILE*fp;fp=fopen("文件名","文件操作模式");
或者将上述两句合并为下面一句:
FILE*fp=fopen("文件名","文件操作模式");
其功能是打开一个由“文件名”指向的外部文件,返回值是一个指向该文件的文件指针。在文件名中可以指明存储盘及文件路径。若文件打开成功,则fp为一非空指针,否则fp值为NULL。表10-1是“文件操作模式”的类别及含义。.
例如:
FILE*fp;
fp=fopen("d:\\class.txt","r");
其功能是以只读方式在D盘根目录下打开名为“class.txt”的文本文件,允许进行读操作,并使fp指向该文件。C语言中,两个反斜线“\\”属于转义字符,代表反斜杠字符“\”。
又如:
FILE*fp;
fp=fopen("c:\\class.txt","rb");
其功能是打开C盘根目录下的文件“class.txt”,只允许按二进制方式进行读操作。
对于文件操作模式,有以下几点说明:
(1)凡用“r”打开一个文件时,该文件必须已经存在,且只能从该文件读取数据。
(2)凡用“w”打开的文件,只能向该文件写入。若打开的文件不存在,则以指定的文件名建立该文件。若打开的文件已经存在,则将该文件删去,以指定的文件名重建一个新文件。
(3)若要向一个已存在的文件追加新的信息,只能用追加(“a”)方式打开文件。但此时该文件必须是存在的,否则将会出错。
(4)在打开一个文件时,如果出错,fopen()将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作,并进行相应的处理。
(5)把一个文本文件读入内存时,系统将ASCII码转换成二进制码,而把文件以文本方式写入磁盘时,系统要把二进制码转换成ASCII码,因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换。
(6)标准输入文件(键盘)、标准输出文件(显示器)和标准出错输出文件(显示器)是在程序运行时由系统自动打开的,可直接使用而无须打开与它们相连的终端文件。
例10-1在指定路径下打开一个文件。
上述程序的功能是:如果返回的指针为空,表示不能打开D盘根目录下的“class.txt”文件,则给出提示信息“cannotopenfile!”。程序中的exit(0)表示终止程序执行并返回值0,其在main()函数中的作用相当于return0。
10.2.2文件的关闭
文件一旦使用完毕,要用关闭文件函数把文件关闭,以免出现文件数据丢失等错误。所谓“关闭文件”,就是使文件指针变量不再指向该文件,即让文件指针变量与被关闭的文件“脱钩”。关闭文件还可将未满的输出缓冲区数据写入文件,将未满的输入缓冲区数据取出,以免数据丢失,同时撤销文件信息区和缓冲区,断开文件与内存的联系。C语言提供了关闭文件的fclose()函数,该函数原型也在stdio.h头文件中,其调用格式为
fclose(文件指针);
若关闭文件操作成功,则fclose()函数返回值为0,否则返回EOF(-1)。
例10-2以只读方式打开和关闭一个名为class.txt的二进制文件\n。
10.3文件的读/写
当文件按指定的工作方式打开以后,就可以对文件进行读和写操作了。对文本文件来说,可按字符读写或按字符串读写;对二进制文件来说,可进行成块的读写或格式化的读写。C语言提供了多种文件读/写函数,如表10-2所示,这些函数原型都在stdio.h头文件中。
10.3.1字符读/写函数
fgetc()和fputc()函数分别用于对文本文件进行单个字符的读和写。其调用格式分别为
ch=fgetc(fp); /*fp为文件指针*/
fgetc(fp)函数从文件指针所指向文件的当前位置返回一个字符,并将文件指针指示器移到下一个字符位置。如果文件指示器已到文件末尾,则函数返回一个EOF(EOF是一个符号常量,值为-1,定义在stdio.h头文件中),表示读入的不是正常的字符而是文件结束符。
fputc(ch,fp)函数将字符ch的值写入fp所指向文件的当前位置(文件内部指针指向)处,并将文件内部指针后移一位。fputc()函数的返回值是所写入字符的值,出错时返回EOF。读/写文件操作完成后,应关闭相应文件。
例10-3从键盘多次输入单个字符,存到磁盘文件class.txt中,当输入“#”时结束。
例10-4先将存放于磁盘的指定文本文件的内容按只读方式读取,再将其显示到屏幕上。要求采用带参数的main(),指定的磁盘文件名由命令行方式通过键盘输入。
对于fgetc()和fputc()函数的使用,有以下几点说明:
(1)在fgetc()函数调用中,读取的文件必须是以只读或读/写方式打开的;而在fputc()函数调用中,被写入的文件可用只写、读/写和追加方式打开。
(2)读取字符的结果也可用字符变量保存,例如,ch=fgetc(fp)。
(3)在文件内部用位置指针来指向文件的当前读/写位置,每读/写一次,该指针均向后移动。在文件打开时,该指针由系统自动设置,并总是指向文件的首字节。
(4)在fputc()函数调用中,用只写方式打开一个文件时,如果原来不存在该文件,则在打开时新建立一个以指定名字命名的文件;如果原来已存在一个以该文件名命名的文件,则在打开时将该文件删去,然后重新建立一个新文件。
10.3.2字符串读/写函数
C语言提供的fgets()和fputs()函数分别用于实现对文本文件的字符串读和写操作。这两个函数的调用格式分别为
fgets(字符数组,n,fp);
fputs(字符串,fp);
fgets(字符数组,n,fp)从指定的文件中将长度n-1的字符串读到字符数组中,在最后一个读取的字符后加结束符 '\0'。若在读取n-1个字符之前遇到了换行符或EOF,则读操作结束。若读取数据成功,函数fgets()则返回字符数组的首地址,否则返回NULL。字符数组名也可以由字符指针变量代替,本质上都是将读取的字符串存放在相应的存储区中。
fputs(字符串,fp)向指定文件写入一个字符串,其中字符串可以是字符串常量、字符数组名或字符型指针变量。字符串结束符'\0'不写入。若写入成功,则函数值为0;若写入失败,则返回为EOF。
fgets()和fputs()函数与gets()和puts()函数类似,只是gets()和puts()函数以终端为操作对象,而fgets()和fputs()函数以指定的文本文件为操作对象。
例10-5从test.txt文件中读取字符串,再写入例10-3的class.txt文件,并显示后者的内容。
本例中要对两个文件进行操作,需定义两个文件变量指针。在操作文件以前,应将两个文件以不同的工作方式打开(不分先后),读/写完成后再关闭文件。程序写入文件的同时在屏幕上显示,故程序运行结束后,在屏幕上可看到目标文件class.txt的内容。
例10-6从例10-5的class.txt文件中读入长度为15个字符的字符串并显示。
该程序先定义一个16字节的字符数组string,且以只读方式打开文本文件class.txt,读取15个字符并送入string数组(在数组最后一个单元内将加上 '\0'),然后在屏幕上显示string数组。
例10-7向例10-6中的class.txt文件末尾追加一个字符串,并显示文件内容。
10.3.3格式化读/写函数
C语言提供了对磁盘文件进行格式化读/写的函数fscanf()和fprintf()。这两个函数的调用格式分别为
scanf(文件指针,格式字符串,输入列表);
fprintf(文件指针,格式字符串,输出列表);
fscanf()函数按指定的格式从“文件指针”指向的磁盘文件上将数据读取并存储至“输入列表”指定的数据缓存区中。
fprintf()函数将“输出列表”数据按指定的格式输出到“文件指针”指向的磁盘文件上。
由于C语言引入了这两个格式化输入/输出函数,因此文件在存储格式上满足某种指定格式。例如:
fscanf(fp,"%d%s",&a,str); /*a为整型普通变量,str为字符指针变量或字符数组名*/
fprintf(fp,"%d%s",a,str);
例10-8先将两个学生记录,包括姓名、学号、两科成绩的数据,以格式化的数据格式写入文本文件grades.txt中,再从该文件中以格式化方法读出并显示到屏幕上。
10.3.4数据块读/写函数
前面介绍的几种读/写文件的方法,对于复杂的数据类型无法以整体形式向文件写入或从文件读出。为了解决这个问题,C语言提供成块的读/写方式来操作文件,使数组或结构体等类型可以进行一次性读/写。
C语言提供的数据块读/写函数fread()和fwrite(),可用来读/写一组数据(一个数据块)。数据块读/写函数的调用格式为
fread(buffer,size,n,fp);
fwrite(buffer,size,n,fp);
其中:buffer是一个缓冲区指针,在fread()函数中它表示存放读取数据的首地址,在fwrite()函数中它表示写入数据的首地址;size表示每次读/写的数据项的字节数;n表示要连续读/写的数据项个数;fp表示文件指针。每调用一次数据块读/写函数所传输的总字节数等于n×size。
fread()函数从打开的文件fp中读取n个数据项(每个数据项的长度为size个字节),并放入指定的缓冲区buffer中,所读的字节长度为n × size。函数调用成功后,返回实际读取的数据项个数;若遇文件结束或出错,则返回0。
fwrite()函数把buffer所指向的n个数据项(每个数据项的长度为size个字节)写入已经打开的文件fp中。函数返回值为写到文件中的数据项个数。
例10-9先从键盘输入两个学生数据,并将其写入student.txt文件中,再读取这两个学生的数据使之显示在屏幕上。
通常,若输入数据的格式较为复杂,可采取将各种格式的数据全部当作字符串来输入,然后将字符串转换为所需的格式。C语言提供如下格式转换函数来实现这种操作:
intatoi(char*ptr);
floatatof(char*ptr);
longintatol(char*ptr);
它们分别将字符串转换为整型、浮点型和长整型。在程序中加入这些转换函数后,在程序运行输入数据时,操作者不必记住每种数据的类型,这增强了程序的易用性。使用这些函数时须将其头文件math.h或stdlib.h写在程序的前面。
例10-10将输入的不同格式的数据当作字符串输入例10-8的文件中,然后将其转换,进行文件的成块读/写。
10.4文件的定位
C语言提供了rewind()函数和fseek()函数来对文件内部的位置指针进行移动操作。rewind()函数把位置指针重新移动到文件首位置,该函数无返回值;fseek()函数把位置指针移动到某一指定位置。这两个函数的调用格式为rewind(FILE*fp);fseek(FILE*fp,longoffset,intorigin);
其中:文件指针“fp”指向欲移动的文件。fseek()函数中,位移量“offset”表示移动的字节数且为“long”型数据,以便在被打开的文件的长度大于64KB时不会出错(即文件内部的位置指针的移动范围大于64KB)。当用常量表示位移量时,要加后缀“L”(表示是长整型数)。若位移量为正值,则表示从起始点向文件尾方向移动;若位移量为负值,则表示从起始点向文件首方向移动。起始点“origin”表示从何处开始计算位移量。规定的起始点有3种:文件首、当前位置和文件尾,其表示方法如表10-3所示。
fseek()函数若操作成功,则其返回值为0,否则为非0。例如:
fseek(fp,100L,0); /*将位置指针从文件首向文件尾方向移动100个字节*/
fseek(fp,-10L,1); /*将位置指针从当前位置向文件首方向移动10个字节*/
需要说明的是,fseek()函数一般用于二进制文件。在文本文件中由于要进行转换而产生误差,故往往容易出现因计算误差导致位置指针指向错误的问题。当文件内部的位置指针按要求进行了移动之后,对文件的随机读/写即可用前面介绍的任一种读/写函数进行读/写。常通过fread()和fwrite()函数与fseek()函数配合使用来对一个数据块进行读/写操作。
例10-11从键盘输入字符串到例10-7的class.txt文件中,重新取出时将所有的英文小写字母转换为英文大写字母显示。
例10-12从例10-9中的student.txt文件中读取第二个学生的数据。
10.5文件的检测
常用的文件检测函数有以下几个。(1)文件结束检测函数。其调用格式为feof(文件指针);该函数的功能是判断文件是否处于文件结束位置,如处于文件结束位置,则返回值为非零值,否则为0。
(2)读/写文件出错检测函数。其调用格式为
ferror(文件指针);
该函数的功能是检查文件在用各种输入/输出函数进行读写时是否出错。如ferror()返回值为0,则表示未出错,否则表示有错。
(3)文件出错标志清除函数。其调用格式为
clearerr(文件指针);
该函数的功能是清除出错标志和文件结束标志,使它们为0值。在C程序中,只
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- DB36-T1807-2023-水利水电工程基坑安全监测技术规程-江西省
- 卵巢肿瘤病例讨论
- 护理教学查房实施规范
- 2025年九年级物理力学综合压轴题专项训练试卷(含解题思路)
- 2025年教师教学工作量核算办法:全面优化与实施
- 德语欧标B1水平2024-2025年情景对话模拟试卷:生活对话实战
- 广东省揭阳市惠来县第一中学2024-2025学年高一上学期10月月考地理试题
- 2025年医保知识考试题库及答案:医保政策调整与影响案例分析历年真题解析
- 2025年注册建筑师考试建筑设计办公楼建筑设计试题试卷
- 儿科护理安全护理
- GB/T 70.1-2008内六角圆柱头螺钉
- 联合利华POSM展策划案
- 13-3飞速发展的通信世界 教案
- 下第四单元 崇尚法治精神 复习学案
- 课件:第六章 社会工作项目评估(《社会工作项目策划与评估》课程)
- 最新超星尔雅《从爱因斯坦到霍金的宇宙》期末考试答案题库完整版
- 信息技术网络安全(教案)
- 小学语文近义词辨析的方法
- 河南省成人高等教育毕业生毕业资格审查表(新表)
- 长方体和正方体表面积的练习课课件
- 设计的开始:小型建筑设计课件
评论
0/150
提交评论