版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第12章 处理文件,如果计算机只能处理存储在主内存中的数据,则应用程序的适用范围和多样性就会受到相当大的限制。事实上,所有重要的商业应用程序所需的数据量远远大于主内存所能提供的数据量,常常需要具备处理外部设备(例如固定磁盘)所存储的数据的能力。本章将了解如何处理外部设备上的文件数据 。,12.1 文件的概念,在前面的所有例子中,用户在执行程序时输入的任何数据,在程序结束后都会消失。此时如果用户要用相同的数据执行程序,就必须重新输入一遍。这种方式不仅不方便,还使编程任务无法完成 。 文件中的位置 文件流,12.1.1 文件中的位置,文件有开头和结尾,还有一个当前位置,通常定义为从文件头到当前位置
2、有多少个字节数,如图12-1所示。当前位置就是发生文件操作(读写文件的动作)的地方。当前位置可以移动到文件的其他地方去。新的当前位置可以指定为距离文件开头的偏移量,或在某些情况下,指定为从前一个当前位置算起的正或负偏移量 。,12.1.2 文件流,C库提供了读写数据流的函数。流是外部数据源或数据目的地的抽象表示,所以键盘、显示器上的命令行和磁盘文件都是流。因此,可以使用输入输出函数读写映射为流的任意外部设备 。,12. 2 文件访问,磁盘上的每个文件都有一个名称,文件命名规则由操作系统确定。如果一个处理文件的程序只能处理特殊名字的文件,就不是很方便,需要为每个要处理的文件编写不同的程序。因此,
3、在C语言中处理文件时,程序通过文件指针来引用文件。文件指针是一个抽象指针,关联到一个特定的文件上,所以程序可以在不同的情况下处理不同的文件。文件指针指向表示流的结构。本章的示例使用微软的Windows文件名。如果使用其他操作系统(例如UNIX)就需要适当地调整文件的名称 。 打开文件 文件重命名 关闭文件 删除文件,12. 2.1 打开文件,将内部文件指针变量关联到一个特定的外部文件名称上的过程称为打开文件。调用标准库函数fopen()就可以打开文件,该函数返回特定外部文件的文件指针。fopen()函数在中定义,它的原型如下: FILE *fopen(char *name, char* mod
4、e);,12. 2.2 文件重命名,在许多情况下都需要对文件进行重命名。例如更新文件的内容,创建一个新的、更新过的文件。这需要在创建新的文件后,给它指定一个临时的文件名,然后删除旧文件,再将这个临时的文件名更改成被删掉的文件名。文件重命名非常简单,只需使用rename()函数,它的原型如下: int rename(const char *oldname, const char *newname);,12. 2.3 关闭文件,使用完文件后,需告诉操作系统释放文件指针,这称为关闭文件。这个动作通过调用函数fclose()来完成。这个函数将文件指针作为变元,返回int类型的值。如果成功关闭文件,就返
5、回0,否则返回EOF。函数fclose()的使用方式如下: fclose(pfile); /* Close the file associated with pfile */,12. 2.4 删除文件,现在可以在代码中创建文件,有时也要编程删除文件。此时可以使用在中声明的函数remove(),其用法如下: remove(pfile.txt); 这行语句会从当前目录中删除pfile.txt文件。在调用函数remove()删除文件时,文件不应是打开的,否则,调用函数remove()的动作取决于具体的C实现方式,请参阅库文档说明。 文件的任何动作都需要检查两次,尤其是删除文件的动作 。,12.3 写
6、入文本文件,打开一个文件以用于写入数据后,就可以在程序的任何地方给它写入数据,只要可以访问fopen()为文件设置的文件指针即可。如果要在包含多个函数的任意位置访问文件,就需要确保文件指针有全局作用域,或可以作为变元传送给访问文件的函数 。,12.4 读取文本文件,fgetc()函数与fputc()函数互补,fgetc()从打开的文本文件中读取一个字符。它将文件指针作为唯一的变元,如果读取操作成功,就把读取的字符返回为int类型;否则,返回EOF。fgetc()函数的一般用法如下面的语句所示: mchar = fgetc(pfile); /* Reads a character into mc
7、har */,12.5 将字符串写入文本文件,puts()函数将字符串写入stdout,而函数fputs()会将字符串写入文本文件。它的原型如下: int fputs(char *pstr, FILE *pfile); 第一个变元是要写入文件的字符串指针,第二个变元是文件指针。这个函数的动作有点古怪,它会将字符串写入文件,直到碰到0字符为止,但是0不会写入文件。用fputs()写入文件的不定长的字符串,可以用fgets()将它读取出来。这是因为它是一个字符写入操作,不是二进制写入操作,所以它希望写入的一行文本以换行符结束。这个函数不需要换行符,但是读取文件(使用互补函数fgets()时,换行符
8、会非常有用。,12.6 从文本文件中读入字符串,fputs()的互补函数是fgets(),它可以从文本文件中读入一个字符串。其函数原型如下: char *fgets(char *pstr, int nchars, FILE *pfile); fgets()有3个参数。它会从pfile所指向的文件将字符串读入pstr所指向的内存。 该函数会一直从文件中读取字符串,直到读到了n字符或读入nchars1个字符为止 。,12.7 格式化文件的输入输出,将字符及字符串写入文件比较顺利,但是在程序中一般有许多其他的数据类型。例如,要将数值数据写入文件,就需要更多的操作;要使文件中的内容能让人看得懂,还需要
9、数值数据的字符表示。而格式化文件的输入输出函数提供了这样的机制 。 格式化文件输出 格式化文件输入,12.7.1 格式化文件的输出,在第10章讨论标准流时,就遇到过格式化文件输出的函数。它和printf()语句相同,但有一个额外的参数,名称也稍有不同。它的用法如下: fprintf(pfile, %12d112d%14f, num1, num2, fnum1); 可以看到,这个函数名称比printf()多了一个f(文件),第一个变元是指定输出目的地的文件指针。显然,文件指针需要通过调用fopen()来设定。其余的变元和printf()相同 。,12.7.2 格式化文件的输入,使用fscanf(
10、)函数可以得到格式化文件输入。例如,从文件pfile读入3个变量值,可以使用如下语句: fscanf(pfile, %12d%12d%14f, 这个函数的操作和scanf()对stdin的操作完全相同,只是要从第一个变元指定的文件中得到输入。scanf()函数的使用规则也适用于这个函数的格式字符串和操作。如果发生错误,没有读取输入,函数会返回EOF,否则将读取的值的个数返回为int类型的值 。,12.8 错误处理,本书的例子都只包含最起码的错误检查及报告,因为完整的错误检查和报告代码会占用很大的篇幅,使程序看起来相当复杂。然而在实际的程序中,应尽可能地检查及报告错误 。,12.9 再探文本文件
11、操作模式,前面使用的文本模式都是打开文件的默认操作模式。在C的早期版本中,可以明确指定文件以文本模式打开。为此,只需在已有的指定符后面加上“t”。因此,除了原来的3 个模式之外,还有3 个模式指定符wt、rt和at。这里提及它们,因为读者可能在其他C程序中遇到它们。尽管大多数编译器支持它们,但它们不是当前C标准的内容,所以最好不要在代码中使用它们 。,12.10 二进制文件的输入输出,文件操作除了文本模式外,还有一个二进制模式。在这个模式下,不转换数据,也不需用格式字符串控制输入输出,所以它比文本模式简单。二进制模式将内存的数据直接传送到文件中。文本模式下具有特殊意义的字符,如n和0,在二进制
12、模式下就没有意义了 。 指定二进制模式 写入二进制文件 读取二进制文件,12.10.1 指定二进制模式,要指定二进制模式,只需在基本打开模式指定符后附加b。因此,打开模式指定符wb表示写入二进制文件,rb表示读取二进制文件,ab表示将数据追加到二进制文件的末尾,rb+表示读写二进制文件 。,12.10.2 写入二进制文件,写入二进制文件的函数是fwrite()。最好用一个例子来解释它。假设用下面的语句打开文件,以执行写入操作: char *filename = myfile.bin; FILE *pfile = fopen(filename, wb);,12.10.3 读取二进制文件,二进制文
13、件以读取模式打开后,就可以使用fread()函数读取它。使用和写入二进制文件例子中相同的变量读取文件,语句如下: size_t wcount = fread( pdata, sizeof(long), num_items, pfile);,12.11 读取二进制文件,在许多应用程序中,需要能随机访问文件中的数据,而不是按顺序访问它们。某些信息存储在文件的中央,因此必须从文件的开头读起,直到找到需要的信息为止。但如果文件包含几百万项,就要花相当多的时间。 文件定位操作 找出我们在文件中的位置 在文件中设定位置,12.11.1 文件定位操作,文件定位有两个方面:找出当前我们在文件中的位置,然后移动
14、到文件中某个特定的位置。前者是后者的基础:如果不知道在文件的什么地方,就不可能知道如何到达要去的地方 。,12.11.2 找出我们在文件中的位置,有两个函数可以指出我们在文件中的位置,它们相当类似,但并不相同。它们是互补的位置函数。第一个函数是ftell(),它的原型是: long ftell(FILE *pfile);,12.11.3 在文件中设定位置,ftell()的互补函数是fseek(),它的原型如下: int fseek(FILE *pfile, long offset, int origin);,12.12 使用临时文件,程序执行时,常需要一个工作文件来存储中间结果,程序结束后,就
15、删除它。本章计算质数的程序就是一个例子,文件仅在计算过程中需要。 使用临时文件的函数有两个,它们各有优缺点 。 创建临时文件 创建唯一的文件名,12.12.1 创建临时文件,第一个函数会自动创建临时文件。它的原型如下: FILE *tmpfile(void); 这个函数没有参数,返回临时文件的指针。如果因某种原因不能创建这个文件,例如磁盘满了,这个函数会返回NULL。这个文件会以更新方式创建并打开,所以可以读写它。这个文件在程序结束后会自动删除,所以不需要任何整理操作。我们永远不知道这个文件叫什么,12.12.2 创建唯一的文件名,第二个方法是使用一个可以提供唯一文件名的函数,这个临时的文件名
16、由程序员指定。函数的原型如下: char *tmpnam(char *filename);,12.13 更新二进制文件,有3个打开模式可用于更新二进制文件: 修改文件的内容 从键盘读取记录 将记录写入文件 从文件中读取记录 写入文件 列出文件内容 更新已有的文件内容,12.13.1 修改文件的内容,扩展上一个例子,以使用另外两个二进制更新模式。本节要添加功能,以更新文件中的已有记录,添加记录或删除文件。这个程序相当复杂,所以最好将其操作分解到函数中。文件仍包含姓名记录,这样由姓名和年龄组成的记录的长度就互不相同。在修改文件的内容时,可以看到因此带来的复杂性。,12.13.2 从键盘读取记录,编
17、写一个函数,从stdin中读取姓名字符串和年龄值,将它们存储在Record对象中。该函数的原型如下: struct Record *getrecord(struct Record *precord); 这个函数的参数是指向已有Record结构对象的指针,其返回值是该对象的地址。因此,可以把该函数的调用作为Record *类型的变元传送给另一个函数 。,12.13.3 将记录写入文件,现在,定义一个函数,将Record对象的成员写入FILE *指针指向的文件中,该函数的原型如下: void writerecord(struct Record *precord, FILE *pFile); 第一个
18、参数是指向Record结构的指针,该结构的姓名和年龄成员要写入文件。第二个参数是文件指针,12.13.4 从文件中读取记录,下面是从文件中读取一个记录的函数的原型: struct Record *readrecord(struct Record *precord, FILE *pFile); 要读取的文件用第二个参数指定,即文件指针。为了方便,返回值是作为第一个参数传送的地址。,12.13.5 写入文件,下面是将任意个记录写入文件的函数原型,其中记录是从键盘上输入的: void writefile(char *filename, char *mode); 第一个参数是要写入的文件名,这表示该函
19、数要打开文件。第二个参数是要使用的文件打开模式。将模式指定为“wb+”,writefile()函数就会删除文件的原始内容,再将数据写入文件。如果文件不存在,就用指定的名称创建一个文件。如果模式指定为“ab+”,记录就追加到已有的文件中,如果文件不存在,就创建一个新文件。,12.13.6 列出文件内容,将文件中的记录输出到标准输出流中的函数原型如下: void listfile(char *filename); 其参数是文件名,所以函数要先打开文件,操作完成后关闭它。,12.13.7 更新已有的文件内容,更新文件中的已有记录增加了复杂性,因为文件中的姓名有不同的长度。不能简单地覆盖已有的记录,因为用于替换的记录可能在原来的空间中放不下。如果新记录的长度与原记录相同,就可以覆盖它,如果不同,就只能将数据写入一个新文件。下面是更新文件的函数的原型: void updatefile(char *filename); 唯一的参数是文件名,所以该函数会查找出要更新的记录,并打开和关闭文件。,12.14 更新已有的文件内容,12.15 更新已有的文件内容,本章的最后将前面所学的内容应用于最后一个程序。这个程
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 产品代理合同简单常用版样书
- 高层住宅小区购房合同
- 打机井师用工合同范文
- 二手装载机的买卖合同范文
- 工程造价工作流程图
- 重庆市南川区2024年七年级上学期期中数学试题【附答案】
- 二年级上册-语文易考题造句
- 湖南省部分学校20242025学年高一上学期10月考试语文试卷2
- 1122三角形的外角(分层练习)-2023-2024学年八年级数学上册(人教版)
- 工程项目管理考试试题(同名19362)
- 干成孔旋挖灌注桩施工工艺
- 大数据与智能交通简介
- 车辆轴温智能探测系统(THDS)-防松铁丝的绑扎方法
- 大班数学《数字接龙》
- 全国优质课一等奖小学四年级教科版科学《用气球驱动小车》公开课课件(内嵌音频视频)
- 第8课 隋唐政治演变与民族交融
- 山东省菏泽市东明县2023-2024学年七年级上学期期中数学试题
- 马工程版《中国经济史》各章思考题答题要点及详解
- 江苏省高校省级
- 江苏省扬州市梅岭中学教育集团2023-2024学年八年级上学期期中英语试卷
- 动力电池的结构及工作原理
评论
0/150
提交评论