文件操作(6)课件.ppt
1第第4讲讲文件操作文件操作什么是文件系统?什么是文件系统?n大容量大容量直接存取直接存取的的磁盘存储器磁盘存储器以及以及顺序存取顺序存取的的磁磁带存储器带存储器等的出现,为程序和数据等软件资源的等的出现,为程序和数据等软件资源的透明存取提供了物质基础,这导致了对软件资源透明存取提供了物质基础,这导致了对软件资源管理质的飞跃管理质的飞跃文件系统文件系统的出现。的出现。几个误区几个误区n首先,需要澄清对于文件系统的一些错误理首先,需要澄清对于文件系统的一些错误理解:解:n经常有这样的说法,经常有这样的说法,“我的硬盘是我的硬盘是FAT32格格式的式的”,“C盘是盘是NTFS格式格式”等,它们的等,它们的错误在于,错误在于,NTFS或是或是FAT32并不是并不是硬盘格硬盘格式式,而是,而是管理文件的系统格式管理文件的系统格式n其次刚买回来的硬盘并没有文件系统,必须其次刚买回来的硬盘并没有文件系统,必须使用使用FDISK或或Windows2000/XP的分区工的分区工具等对其进行分区并具等对其进行分区并格式化格式化后才会有管理后才会有管理文件的系统,因此文件的系统,因此文件系统是对应分区的,文件系统是对应分区的,而不是硬盘而不是硬盘,不管是将硬盘分成一个分区,不管是将硬盘分成一个分区,还是几个分区。还是几个分区。什么是文件系统?什么是文件系统?n举个通俗的比喻,一块硬盘就像一个块空地,文举个通俗的比喻,一块硬盘就像一个块空地,文件就像不同的材料,我们首先得根据自己的目的件就像不同的材料,我们首先得根据自己的目的在空地上建起不同的仓库(在空地上建起不同的仓库(分区分区)n并且指定好并且指定好(格式化)(格式化)每个仓库对材料的管理规每个仓库对材料的管理规范(范(文件系统文件系统),这样才能将材料运进仓库保管。),这样才能将材料运进仓库保管。n所以一个磁盘可以有多个逻辑分区,也就可以对所以一个磁盘可以有多个逻辑分区,也就可以对应多个文件系统。应多个文件系统。什么是文件系统?什么是文件系统?n文件本身不会受所在分区的文件系统影响文件本身不会受所在分区的文件系统影响,就像,就像同样是汽车轮胎在同样是汽车轮胎在A仓库可能直接堆在地上,而仓库可能直接堆在地上,而B仓库则会挂在墙上,仅仅是仓库则会挂在墙上,仅仅是放置和管理方法放置和管理方法不同不同而已而已n因此,在因此,在NTFS分区和分区和FAT32分区的文件可以随意分区的文件可以随意在分区间移动,内容不会因此产生任何不同。在分区间移动,内容不会因此产生任何不同。什么是文件系统什么是文件系统n操作系统中与管理文件有关的软件和数据称为文操作系统中与管理文件有关的软件和数据称为文件系统件系统。n它负责为用户建立文件,撤消、读写、修改和复它负责为用户建立文件,撤消、读写、修改和复制文件,还负责完成对文件的按名存取和进行存制文件,还负责完成对文件的按名存取和进行存取控制。取控制。Widows的主流文件系统的主流文件系统nFAT(Table)是是“文件分配表文件分配表”的意的意思。对我们来思。对我们来说,它的意义在于对硬盘分区的管理。说,它的意义在于对硬盘分区的管理。nFAT16、FAT32、NTFS是目前最常见的三种文件是目前最常见的三种文件系统。系统。Widows的主流文件系统的主流文件系统nFAT16:我们以前用的我们以前用的DOS、Windows95都使都使用用FAT16文件系统文件系统n现在常用的现在常用的Windows98/2000/XP等系统均支持等系统均支持FAT16文件系统。它最大可以管理大到文件系统。它最大可以管理大到2GB的分的分区,但每个分区最多只能有区,但每个分区最多只能有65525个簇(簇是磁个簇(簇是磁盘空间的配置单位)。盘空间的配置单位)。n随着硬盘或分区容量的增大,每个簇所占的空间随着硬盘或分区容量的增大,每个簇所占的空间将越来越大,从而导致硬盘空间的浪费。将越来越大,从而导致硬盘空间的浪费。Widows的主流文件系统的主流文件系统nNTFS(英文全称为(英文全称为“NT):微软微软WindowsNT内核的系列操作系统支持的、一个特别为网络和内核的系列操作系统支持的、一个特别为网络和磁盘配额、文件加密等管理安全特性设计的磁盘磁盘配额、文件加密等管理安全特性设计的磁盘格式。格式。n随着以随着以NT为内核的为内核的Windows2000/XP的普及,的普及,很多个人用户开始用到了很多个人用户开始用到了NTFS。nNTFS也是以簇为单位来存储数据文件,但也是以簇为单位来存储数据文件,但NTFS中簇的大小并不依赖于磁盘或分区的大小。中簇的大小并不依赖于磁盘或分区的大小。n簇尺寸的缩小不但降低了磁盘空间的浪费,还减簇尺寸的缩小不但降低了磁盘空间的浪费,还减少了产生磁盘碎片的可能。少了产生磁盘碎片的可能。NTFS支持文件加密管支持文件加密管理功能,可为用户提供更理功能,可为用户提供更高层次的安全保证。高层次的安全保证。Widows的主流文件系统的主流文件系统n只有只有WindowsNT/2000/XP才能识别才能识别NTFS系统,系统,Windows9x/Me以及以及DOS等操作系统都不能支持、识别等操作系统都不能支持、识别NTFS格式的磁盘。格式的磁盘。n由于由于DOS系统不支持系统不支持NTFS系统,所以最好不要将系统,所以最好不要将C:盘制盘制作为作为NTFS系统,这样在系统崩溃后便于在系统,这样在系统崩溃后便于在DOS系统下修系统下修复。复。n而且这种情况下,如果不知道而且这种情况下,如果不知道C盘是盘是NTFS格式,在格式,在DOS下进行对下进行对C盘格式化操作,那么盘格式化操作,那么格式化的不是格式化的不是C盘而是盘而是D盘!盘!。Linux的操作系统的主流文件系统的操作系统的主流文件系统nlinux操作系统的磁盘分区格式与其他操作系统完全不同,操作系统的磁盘分区格式与其他操作系统完全不同,至少需要两个专门的分区:至少需要两个专门的分区:n一种是一种是linuxnative主分区主分区n一种是一种是linuxswap交换分区。这两种分区格式的安全性与交换分区。这两种分区格式的安全性与稳定性极佳,结合稳定性极佳,结合linux操作系统后,操作系统后,死机的机会大大减死机的机会大大减少少。n但是,目前支持这一分区格式的操作系统只有但是,目前支持这一分区格式的操作系统只有linuxLinux的操作系统的主流文件系统的操作系统的主流文件系统n还可以创建哪些分区(仅列常用几种)。还可以创建哪些分区(仅列常用几种)。/boot分区分区,它包含了操作系统的内核和在启动系统过程,它包含了操作系统的内核和在启动系统过程中所要用到的文件,建这个分区是有必要的。这个分区的中所要用到的文件,建这个分区是有必要的。这个分区的大小约在大小约在50MB100MB之间。之间。n/usr分区分区,是,是RedHatLinux系统存放软件的地方,如有系统存放软件的地方,如有可能应将最大空间分给它。可能应将最大空间分给它。/home分区分区,是用户的,是用户的home目录所在地,这个分区的大目录所在地,这个分区的大小取决于有多少用户。小取决于有多少用户。Linux的操作系统的主流文件系统的操作系统的主流文件系统n/var/log分区分区,是系统日志记录分区,如果设立了这一单独的分区,这样即使,是系统日志记录分区,如果设立了这一单独的分区,这样即使系统的日志文件出现了问题,它们也不会影响到操作系统的主分区。系统的日志文件出现了问题,它们也不会影响到操作系统的主分区。n/tmp分区分区,用来存放临时文件。这对于多用户系统或者网络服务器来说是有,用来存放临时文件。这对于多用户系统或者网络服务器来说是有必要的。这样即使程序运行时生成大量的临时文件,或者用户对系统进行了必要的。这样即使程序运行时生成大量的临时文件,或者用户对系统进行了错误的操作,文件系统的其它部分仍然是安全的。因为文件系统的这一部分错误的操作,文件系统的其它部分仍然是安全的。因为文件系统的这一部分仍然还承受着读写操作,所以它通常会比其它的部分更快地发生问题。仍然还承受着读写操作,所以它通常会比其它的部分更快地发生问题。n/bin分区分区,存放标准系统实用程序。,存放标准系统实用程序。n/dev分区分区,存放设备文件。,存放设备文件。n/opt分区分区,存放可选的安装的软件。,存放可选的安装的软件。n/sbin分区分区,存放标准系统管理文件。,存放标准系统管理文件。上面介绍了几个常用的分区,一般来说我们需要一个上面介绍了几个常用的分区,一般来说我们需要一个SWAP分区,一个分区,一个/boot分区,一个分区,一个/usr分区,一个分区,一个/home分区,一个分区,一个/var/log分区。当然这没有什么分区。当然这没有什么规定,完全是依照你个人来定的。规定,完全是依照你个人来定的。LinuxLinux支持的文件系统支持的文件系统LinuxLinux采用采用虚拟文件系统技术虚拟文件系统技术,可支持多,可支持多种常见的文件系统,并允许用户在不同的磁种常见的文件系统,并允许用户在不同的磁盘分区上安装不同的文件系统。盘分区上安装不同的文件系统。LinuxLinux支持的文件系统类型主要有:支持的文件系统类型主要有:msdosmsdos:MS-DOSMS-DOS采用的采用的FATFAT文件系统文件系统nVfatVfat:WindowsWindows中通用的文件系统中通用的文件系统nsysVsysV:UNIXUNIX中最常用的中最常用的system Vsystem V文件系统文件系统nnfsnfs:网络文件系统:网络文件系统niso9660iso9660:CD-ROMCD-ROM的标准文件系统的标准文件系统extnext是第一个专门为开发的是第一个专门为开发的Linux的文件系统类型,的文件系统类型,叫做扩展文件系统。叫做扩展文件系统。n它是它是1992年年4月完成的,对月完成的,对Linux早期的发展产生早期的发展产生了重要作用。但是,由于其在稳定性、速度和兼了重要作用。但是,由于其在稳定性、速度和兼容性上存在许多缺陷,现在已经很少使用了。容性上存在许多缺陷,现在已经很少使用了。ext2next2是为解决是为解决ext文件系统的缺陷而设计的可扩展的、高文件系统的缺陷而设计的可扩展的、高性能的文件系统,它又被称为二级扩展文件系统。性能的文件系统,它又被称为二级扩展文件系统。next2是是1993年发布的,设计者是年发布的,设计者是ReyCard。next2可以支持可以支持256字节的长文件名字节的长文件名,其单一文件大小和文,其单一文件大小和文件系统本身的容量上限与文件系统本身的簇大小有关。件系统本身的容量上限与文件系统本身的簇大小有关。n2000年以前几乎所有的年以前几乎所有的Linux发行版都使用发行版都使用ext2作为默认作为默认的文件系统。的文件系统。ext3next3被设计成是被设计成是ext2的升级版本,尽可能方便用户从的升级版本,尽可能方便用户从ext2向向ext3迁移。迁移。n和和ext2相比,相比,ext3提供了更佳的安全性,这就是数据日志提供了更佳的安全性,这就是数据日志和元数据日志之间的不同。和元数据日志之间的不同。next3是一种日志式文件系统,日志式文件系统的优越性在是一种日志式文件系统,日志式文件系统的优越性在于由于文件系统都有于由于文件系统都有快取层快取层参与运作,如不使用时必须将参与运作,如不使用时必须将文件系统卸下,以便将文件系统卸下,以便将快取层快取层的资料写回磁盘中。的资料写回磁盘中。ReiserFSnReiserFS的第一次公开亮相是在的第一次公开亮相是在1997年年7月月23日,日,HansReiser把他的基于平衡树结把他的基于平衡树结构的构的ReiserFS文件系统在网上公布。文件系统在网上公布。nReiserFS被看作是一个更加激进和现代的被看作是一个更加激进和现代的文件系统。文件系统。Linux支持多种文件系统支持多种文件系统nLinux支持多种文件系统,如支持多种文件系统,如ext、ext2、minix、iso9660、msdos、fat、vfat、nfs等。等。n在这些具体文件系统的上层,在这些具体文件系统的上层,Linux提供了虚拟文提供了虚拟文件系统(件系统(VFS)来统一它们的行为,)来统一它们的行为,虚拟文件系虚拟文件系统为不同的文件系统与内核的通信提供了一致的统为不同的文件系统与内核的通信提供了一致的接口接口。n下图给出了下图给出了Linux中文件系统的关系:中文件系统的关系:27C语言对文件的操作语言对文件的操作-概述概述n在程序运行时,在程序运行时,程序本身和数据一般都存放在内程序本身和数据一般都存放在内存中存中。当程序运行结束后,存放在内存中的数据。当程序运行结束后,存放在内存中的数据被释放。被释放。n如果需要长期保存程序运行所需的原始数据,或如果需要长期保存程序运行所需的原始数据,或程序运行产生的结果,程序运行产生的结果,就必须以文件形式存储到就必须以文件形式存储到外部存储介质上。外部存储介质上。n这就涉及到文件的操作这就涉及到文件的操作Linux中文件系统的关系中文件系统的关系29两类函数两类函数n在在Linux平台下对文件编程可以使用两类函数:平台下对文件编程可以使用两类函数:n(1)Linux操作系统文件操作系统文件API;n(2)C语言语言I/O库函数。库函数。n前者依赖于前者依赖于Linux系统调用系统调用n后者实际上与操作系统是独立的,因为在任何操后者实际上与操作系统是独立的,因为在任何操作系统下,使用作系统下,使用C语言语言I/O库函数操作文件的方法库函数操作文件的方法都是相同的。都是相同的。n本章将对这两种方法进行实例讲解。本章将对这两种方法进行实例讲解。30Linux的文件描述符和流的文件描述符和流n流流是标准是标准C语言语言I/O库提出来的概念,隐藏了文件库提出来的概念,隐藏了文件描述符,以更抽象的概念代替。描述符,以更抽象的概念代替。n用标准用标准I/O库函数打开或创建文件时,返回一个库函数打开或创建文件时,返回一个FILE结构的指针,该结构包含了文件描述符、缓结构的指针,该结构包含了文件描述符、缓冲区地址、缓冲区大小等信息。冲区地址、缓冲区大小等信息。n有有3个预定义的流于个预定义的流于3个预定义的文件描述符对应:个预定义的文件描述符对应:stdin,stdout,stderr,要使用这,要使用这3个流必须包个流必须包含头文件含头文件322.Linux文件文件APInLinux的文件操作的文件操作API涉及到创建、打开、读写和涉及到创建、打开、读写和关闭文件关闭文件n2.1创建创建nintcreat(constchar*,mode_tmode);n参数参数mode指定新建文件的存取权限,它同指定新建文件的存取权限,它同umask一起决定文件的最终权限一起决定文件的最终权限(mode&umask),其中),其中umask代表了文件在代表了文件在创建时需要去掉的一些存取权限。创建时需要去掉的一些存取权限。33系统调用系统调用umask()numask可通过系统调用可通过系统调用umask()来改变:来改变:nintumask(intnewmask);n该调用将该调用将umask设置为设置为newmask,然后返回,然后返回旧的旧的umask,它只影响读、写和执行权限。,它只影响读、写和执行权限。342.2打开文件打开文件nintopen(constchar*pathname,intflags);nintopen(constchar*pathname,intflags,mode_tmode);nopen函数有两个形式,其中函数有两个形式,其中pathname是我们要是我们要打开的文件名打开的文件名(包含路径名称,缺省是认为在当前包含路径名称,缺省是认为在当前路径下面路径下面),flags可以去下面的一个值或者是几个可以去下面的一个值或者是几个值的组合:值的组合:35flags36n如果使用了如果使用了O_CREATE标志,则使用的函数是标志,则使用的函数是nintopen(constchar*pathname,intflags,mode_tmode);n这个时候我们还要指定这个时候我们还要指定mode标志,用来表示文件标志,用来表示文件的访问权限。的访问权限。nmode可以是以下情况的组合:可以是以下情况的组合:37mode38Mode的标志位的标志位n除了可以通过上述宏进行除了可以通过上述宏进行“或或”逻辑产生标志以逻辑产生标志以外,外,n也可以自己用数字来表示:也可以自己用数字来表示:nLinux总共用总共用5个数字来表示文件的各种权限:第个数字来表示文件的各种权限:第一位表示设置用户一位表示设置用户ID;第二位表示设置组;第二位表示设置组ID;第;第三位表示用户自己的权限位;第四位表示组的权三位表示用户自己的权限位;第四位表示组的权限;最后一位表示其他人的权限。限;最后一位表示其他人的权限。3912345用户用户ID组组ID用户权限用户权限组的权限组的权限他人权限他人权限Mode的标志位的标志位n每个数字可以取每个数字可以取1(执行权限执行权限)、2(写权限写权限)、4(读权限读权限)、0(无无)或者是这些值的和。例如,要创建一个用户可读、可或者是这些值的和。例如,要创建一个用户可读、可写、可执行,但是组没有权限,其他人可以读、可以执行写、可执行,但是组没有权限,其他人可以读、可以执行的文件,并设置用户的文件,并设置用户ID位。位。n那么,应该使用的模式是那么,应该使用的模式是1(设置用户设置用户ID)、0(不设置组不设置组ID)、7(1+2+4,读、写、执行,读、写、执行)、0(没有权限没有权限)、5(1+4,读、执,读、执行行)即即10705:4012345用户用户ID组组ID用户权限用户权限组的权限组的权限他人权限他人权限0、10、10无无1读读2写写4执行执行0无无1读读2写写4执行执行0无无1读读2写写4执行执行nopen(test,O_CREAT,10705);上述语句等价于上述语句等价于nopen(test,O_CREAT,S_ISUID|S_IRWXU|S_IROTH|S_IXOTH);n如果文件打开成功,如果文件打开成功,open函数会返回一个文件描函数会返回一个文件描述符,以后对该文件的所有操作就可以通过对这述符,以后对该文件的所有操作就可以通过对这个个文件描述符文件描述符进行操作来实现。进行操作来实现。4112345用户用户ID组组ID用户权限用户权限组的权限组的权限他人权限他人权限0、10、10无无1读读2写写4执行执行0无无1读读2写写4执行执行0无无1读读2写写4执行执行注意:注意:n以以O_CREAT为标志的为标志的open实际上实现了文件创实际上实现了文件创建的功能,因此,下面的函数等同建的功能,因此,下面的函数等同creat()函数:函数:nintopen(pathname,O_CREAT|O_WRONLY|O_TRUNC,mode);422.3读写读写n在文件打开以后(打开文件才能创建一个文件描在文件打开以后(打开文件才能创建一个文件描述符)述符),我们才可对文件进行读写了,我们才可对文件进行读写了,Linux中提中提供文件读写的系统调用是供文件读写的系统调用是read、write函数:函数:nintread(intfd,constvoid*buf,size_tlength);nintwrite(intfd,constvoid*buf,size_tlength);432.3读写读写n其中参数其中参数buf为指向缓冲区的指针,为指向缓冲区的指针,length为缓冲为缓冲区的大小(以字节为单位)。区的大小(以字节为单位)。n函数函数read()实现从文件描述符实现从文件描述符fd所指定的文件中所指定的文件中读取读取length个字节到个字节到buf所指向的缓冲区中,所指向的缓冲区中,返回返回值为实际读取的字节数值为实际读取的字节数。n函数函数write实现将把实现将把length个字节从个字节从buf指向的缓指向的缓冲区中写到文件描述符冲区中写到文件描述符fd所指向的文件中,所指向的文件中,返回返回值为实际写入的字节数。值为实际写入的字节数。n当然文件的读写指针也随之移动!当然文件的读写指针也随之移动!442.4定位定位n对于随机文件,我们可以随机的指定位置读写,对于随机文件,我们可以随机的指定位置读写,使用如下函数进行定位:使用如下函数进行定位:nintlseek(intfd,offset_toffset,intwhence);nlseek()将文件读写指针相对将文件读写指针相对whence移动移动offset个个字节。操作成功时,返回文件指针相对于文件头字节。操作成功时,返回文件指针相对于文件头的位置。参数的位置。参数whence可使用下述值可使用下述值nSEEK_SET:相对文件开头:相对文件开头SEEK_CUR:相对文件读写指针的当前位置:相对文件读写指针的当前位置SEEK_END:相对文件末尾:相对文件末尾452.4定位定位noffset可取负值,例如下述调用可将文件指针相可取负值,例如下述调用可将文件指针相对当前位置向前移动对当前位置向前移动5个字节:个字节:nlseek(fd,-5,SEEK_CUR);n由于由于lseek函数的返回值为文件指针相对于文件头函数的返回值为文件指针相对于文件头的位置,因此下列调用的返回值就是文件的长度:的位置,因此下列调用的返回值就是文件的长度:nlseek(fd,0,SEEK_END);462.5关闭文件关闭文件n当我们操作完成以后,我们要关闭文件了,只要当我们操作完成以后,我们要关闭文件了,只要调用调用close就可以了,其中就可以了,其中fd是我们要关闭的文件是我们要关闭的文件描述符:描述符:nintclose(intfd);47实例编程实例编程n例程:编写一个程序,在当前目录下创建用户可例程:编写一个程序,在当前目录下创建用户可读写文件读写文件“hello.txt”,在其中写入,在其中写入“Hello,ChengduCollegeofUESTC”,关闭该文件。再,关闭该文件。再次打开该文件,读取其中的内容并输出在屏幕上。次打开该文件,读取其中的内容并输出在屏幕上。48程序实例程序实例49运行结果运行结果5051范例程序阅读范例程序阅读52范例程序阅读范例程序阅读53543.用用C语言库函数对文件操作语言库函数对文件操作nC库函数的文件操作实际上是独立于具体的操作库函数的文件操作实际上是独立于具体的操作系统平台的,不管是在系统平台的,不管是在DOS、Windows、Linux还是在还是在VxWorks中都是这些函数,也就是说这写中都是这些函数,也就是说这写都是都是国际通用函数国际通用函数:n问题:问题:用用C语言库函数对文件操作与利用语言库函数对文件操作与利用API函数函数操作文件的关系是什么?操作文件的关系是什么?55文件类型文件类型FILEn系统给每个打开的文件都在内存中开辟一个区域每个打开的文件都在内存中开辟一个区域,用于存放文件的有关信息(如文件名、文件位置等)。n这些信息保存在一个结构体类型变量中,该结构体类型由系统定义、取名为FILE。n特别注意特别注意:结构体类型名“FILE”必须大写。3.1文件的打开与关闭n对文件进行操作之前,必须先打开该文件;使用对文件进行操作之前,必须先打开该文件;使用结束后,应立即关闭,以免数据丢失。结束后,应立即关闭,以免数据丢失。n语言规定了标准输入输出函数库语言规定了标准输入输出函数库n用用fopen()函数函数打开一个文件打开一个文件n用用fclose()函数函数关闭一个文件。关闭一个文件。补充:根据文件的存储形式分类补充:根据文件的存储形式分类n根据文件的存储形式根据文件的存储形式,可分为两大类:n1.ASCII码文件(文本文件)n2.二进制文件。补充:补充:ASCII码文件码文件n ASCII码文件码文件的每1个字节存储1个字符,因而便于对字符进行逐个处理。n但一般占用存储空间较多,而且要花费转换时间(二进制与ASCII码之间的转换)。补充:补充:二进制文件二进制文件n二进制文件二进制文件是把内存中的数据,原样输出到磁盘文件中。n 可以节省存储空间和转换时间,但1个字节并不对应1个字符,n 不能直接输出字符形式。文件的打开fopen()函数n1原型:原型:FILE*fopen(文件名,操作方式);nFILE*fopen(constchar*path,constchar*mode);n2功能:功能:返回一个指向指定文件的指针。n注:对文件操作的库函数,函数原型均在头文件stdio.h中。n其中:其中:n(1)“文件名文件名”是指要打开(或创建)的文件名。是指要打开(或创建)的文件名。n(2)“操作方式操作方式”如下图所示。如下图所示。n例如:例如:FILE*fp;nfpfopen(“1.txt”,“r”);创建和打开文件创建和打开文件nFILE*fopen(constchar*path,constchar*mode);nfopen()实现打开指定文件,其中的实现打开指定文件,其中的mode为打开为打开模式。模式。n特别要注意的是:特别要注意的是:mode为字符串,和系统调用的为字符串,和系统调用的不同不同nC语言中支持的打开模式如下表:语言中支持的打开模式如下表:62打开模式打开模式63对于文件使用方式有以下几点说明:对于文件使用方式有以下几点说明:n1.文件使用方式由文件使用方式由r,w,a,t,b,+六个字符拼成,六个字符拼成,各字符的含义是:各字符的含义是:nr(read):读读nw(write):写写na(append):追加追加nt(text):文本文件,可省略不写文本文件,可省略不写nb(banary):二进制文件二进制文件n+:读读和和写写对于文件使用方式有以下几点说明:对于文件使用方式有以下几点说明:n2.凡用凡用“r”打开一个文件时,该文件必须已打开一个文件时,该文件必须已经存在,且只能从该文件读出。经存在,且只能从该文件读出。n3.用用“w”打开的文件只能向该文件写入。若打开的文件只能向该文件写入。若打开的文件不存在,打开的文件不存在,则以指定的文件名建立该则以指定的文件名建立该文件文件,若打开的文件已经存在,则将该文件删,若打开的文件已经存在,则将该文件删去,去,重建一个新文件重建一个新文件。对于文件使用方式有以下几点说明:对于文件使用方式有以下几点说明:n4.若要向一个已存在的文件追加新的信息,只若要向一个已存在的文件追加新的信息,只能用能用“a”方式打开文件。但此时该文件必须是方式打开文件。但此时该文件必须是存在的,否则将会出错。存在的,否则将会出错。n5.如果不能实现打开指定文件的操作,则fopen()函数返回一个空空指针指针NULL(其值在头文件stdio.h中被定义为)。n 为增强程序的可靠性,常用下面的方法打开一个文件:if(NULL=(fp=fopen(文件名文件名,操作方式操作方式)printf(cannotopenthisfilen);exit(0);区别区别nfpfopen(“1.txt”,“r”);n所要打开文件与程序文件所要打开文件与程序文件*.c在同一个路径下可在同一个路径下可直接写该文件名,否则要加全部路径。直接写该文件名,否则要加全部路径。nfpfopen(“:DABC1.txt”,“r”);n表示要打开文件表示要打开文件D:ABC1.txtn需要特别注意的是,在需要特别注意的是,在Windows编程环境下语编程环境下语句中有两个句中有两个,why?文件的关闭fcolse()函数n1原型:intfclose(FILE*文件指针文件指针);lint fclose(FILE*stream);n 2功能:关闭“文件指针”所指向的文件。如果正常关闭了文件,则函数返回值为;否则,返回值为非。n 如:nfclose(fp);/*关闭fp所指向的文件*/3.2读写文件读写文件nC库函数支持以库函数支持以字符、字符串等字符、字符串等为单位,支持按为单位,支持按照某中格式进行文件的读写,这一组函数为:照某中格式进行文件的读写,这一组函数为:713.2读写文件读写文件nfread()实现从流实现从流stream中读取加中读取加n个字段,每个个字段,每个字段为字段为size字节,并将读取的字段放入字节,并将读取的字段放入ptr所指的所指的字符数组中,字符数组中,返回实际已读取的字段数返回实际已读取的字段数。在读取。在读取的字段数小于的字段数小于num时,可能是在函数调用时出现时,可能是在函数调用时出现错误,也可能是读到文件的结尾。所以要通过调错误,也可能是读到文件的结尾。所以要通过调用用feof()和和ferror()来判断。来判断。nwrite()实现从缓冲区实现从缓冲区ptr所指的数组中把所指的数组中把n个字段个字段写到流写到流stream中,每个字段长为中,每个字段长为size个字节,个字节,返返回实际写入的字段数。回实际写入的字段数。72数据块的读写函数数据块的读写函数fread()和和fwrite()n数据块的读写函数数据块的读写函数fread()和和fwrite()n 实际应用中,常常要求一次读写一个数据块。为此,ANSI C 标准设置了 fread()和fwrite()函数。n 1原型:intfread(char*buffer,intsize,intcount,FILE*fp);intfwrite(char*buffer,intsize,intcount,FILE*fp);n 2功能:nfread()从fp所指向文件的当前位置开始,一次读入size个字节,重复count次,并将读入的数据存放到从buffer开始的内存中;同时,将读写位置指针向前移动size*count个字节。n其中,buffer是存放读入数据的起始地址。3.3定位文件定位文件n另外,另外,C库函数还提供了读写过程中的定位能力,库函数还提供了读写过程中的定位能力,这些函数包括这些函数包括74文件的读写n文件的读写常用到两个字符的读、写函数n fgetc()nfputc()1.fputc():n 1)原型:)原型:int fputc(字符数据,文件指针);其其中中“字字符符数数据据”,既既可可以以是是字字符符常常量量,也也可可以以是是字符变量。字符变量。n2)功功能能:将字符数据输出到“文件指针”所指向的文件中去,同时将读写位置指针向前移动1个字节(即指向下一个写入位置)。n如如果果输输出出成成功功,则则函函数数返返回回值值就就是是输输出出的的字字符符数数据据;否否则则,返返回回一一个个符符号号常常量量EOF(其其值值在在头头文文件件stdio.h中,被定义为中,被定义为-1)。2.fgetc()nfgetc()n 1)原型:charfgetc(FILE*文件指针文件指针);n 2)功能:从“文件指针”所指向的文件中,读入一个字符,同时将读写位置指针移到下一个字符。格式化的读写函数格式化的读写函数fscanf()和和fprintf()n格式化的读写函数格式化的读写函数fscanf()和和fprintf()与scanf()和printf()函数的功能相似,区别在于:nfscanf()和fprintf()函数的操作对象是指定文件,而scanf()和printf()函数的操作对象是标准输入(stdin)输出 (stdout)文件。n intfscanf(文件指针,文件指针,格式符格式符,输入变量首地址表,输入变量首地址表);nintfprintf(文件指针,文件指针,格式符格式符,输出参量表,输出参量表);n 例如,inti=3;floatf=9.80;nfprintf(fp,%2d,%6.2f,i,f);nfprintf()函数的作用函数的作用是,将变量 i 按%2d格式、变量 f 按n%6.2f格式,以逗号作分隔符,输出到fp所指向的文件中:n 3,9.80(表示1个空格)读写函数的对比读写函数的对比n何数据读写操作。但为方便起见,依下列原则选用:n 1读/写1个字符(或字节)数据时:选用 fgetc()和 fputc()函数n 2读/写1个(或多个)不含格式的数据时:选用 fread()和 fwrite()函数。n 3读/写1个(或多个)含格式的数据时:选用 fscanf()和 fprintf()函数。一道考研题一道考研题n下面的程序的作用是从磁盘下面的程序的作用是从磁盘stu.dat中读取中读取N个学个学生的姓名、学号、成绩,然后在屏幕输出。请将生的姓名、学号、成绩,然后在屏幕输出。请将程序补充完整。程序补充完整。1参考答案:1.stdio.h2.(fp=fopen(“stu.dat”,”rb”)!=NULL)3.fread(stud,sizeof(stuct student),N,fp);4.fclose(fp);3.4文件的定位n文件中有一个文件中有一个读写位置指针,指向当前的读写位,指向当前的读写位置。每次读写置。每次读写1个(或个(或1组)数据后,组)数据后,系统自动将位置指针移动到下一个读写位置上。n如果想改变系统这种读写规律,可使用有关文件如果想改变系统这种读写规律,可使用有关文件定位的函数。定位的函数。文件的定位n一、位置指针复位函数rewind()n1原型:原型:int rewind(FILE*文件指针);n2功能:使文件的位置指针功能:使文件的位置指针返回到文件头返回到文件头。n 二、随机读写与fseek()函数n对于流式文件,既可以顺序读写,也可随机读写,对于流式文件,既可以顺序读写,也可随机读写,关键在于关键在于控制文件的位置指针。控制文件的位置指针。顺序读写与顺序读写与随机读写随机读写随机读写随机读写n所谓所谓顺序读写顺序读写是指,读写完当前数据后,系统自是指,读写完当前数据后,系统自动将文件的位置指针移动到下一个读写位置上。动将文件的位置指针移动到下一个读写位置上。n所谓所谓随机读写随机读写是指,读写完当前数据后,可通过是指,读写完当前数据后,可通过调用调用fseek()函数,将位置指针移动到文件中任何函数,将位置指针移动到文件中任何一个地方。一个地方。返回文件当前位置的函数返回文件当前位置的函数ftell()n由于文件的位置指针可以任意移动,也经常移动,往往容易 迷失当前位置,ftell()就可以解决这个问题。n 1原型:longftell(FILE*文件指针文件指针);n 2功能:返回文件位置指针的当前位置(用相对于文件头的位移量表示)。n 如果返回值为-1L,则表明调用出错。例如:intoffset=ftell(fp);if(offset=-1L)printf(“ftell()errorn”);fseek()函数函数n1原型:n intfseek(FILE*文件指针,文件指针,long位移量,位移量,int参照点参照点);n 2功能:将指定文件的位置指针,从参照点开始,移动指定的字节数。fseek()函数函数n(1)参照点:n用0(文件头)、1(当前位置)和(文件尾)表示。在ANSI C标准中,还规定了下面的名字:n SEEK_SET文件头n SEEK_CUR当前位置,n SEEK_END文件尾n(2)位移量:n以参照点为起点,向前(当位移量时)或后(当位移量时)移动的字节数。在ANSI C标准中,要求位移量为 long int型数据。测试文件是否结束的函数测试文件是否结束的函数feof()n1原型:intfeof(FILE*文件指针文件指针);n2功能:在执行读文件操作时,如果遇到文件尾,则函数返回逻辑真(1);否则,则返回逻辑假(0)。n feof()函数同时适用于ASCII码文件和二进制文件。n一般在读取数据之前,可进行以下测试:while(!feof(fp)实例实例2将第将第2节中