Objective-C-2.0程序设计-第16章-使用文件课件_第1页
Objective-C-2.0程序设计-第16章-使用文件课件_第2页
Objective-C-2.0程序设计-第16章-使用文件课件_第3页
Objective-C-2.0程序设计-第16章-使用文件课件_第4页
Objective-C-2.0程序设计-第16章-使用文件课件_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第16章使用文件

1.目录16.1管理文件和目录:NSFileManager16.2使用路径:NSPathUtilities.h16.3基本的文件操作:NSFileHandle2.16.1管理文件和目录:NSFileManager对于NSFileManager,文件或目录是使用文件的路径名唯一的标石的。每个路径名都是一个NSString对象,它既可以是相对路径名,也可以是完整路径名。相对路径名是相对于当前目录的路径名。所以,文件名copy1.m意味着当前目录中的文件copy1.m。完整路径名,也称为绝对路径名,以斜线/开始,斜线实际上就是一个目录,称为根目录。这个特殊的代字符~用作用户目录的缩写。3.16.1管理文件和目录:NSFileManager4.16.1管理文件和目录:NSFileManager每个文件方法都是对NSFileManager对象的调用,而NSFileManager对象是通过向类发送一条defauItManager消息创建的,如下所示:

NSFileManager*fm;...fm=[NSFileManagerdefaultManager];516.1管理文件和目录:NSFileManager例如,要从当前目录删除名为todolist的文件,首先要创建一个NSFileManager对象(如前面所示),然后调用removeFileAtPath方法,代码如下:

[fmremoveFileAtPath:@”todolist”handler:nil];可以测试返回结果,以确保成功地删除该文件。

if([fmremoveFileAtPath:@”todolist”handler:nil]==NO){ NSLog(@”Couldn’tremovefiletodolist”); return1;}616.1管理文件和目录:NSFileManager除了其他事情之外,属性字典还允许你指定要创建的文件的权限,以便获取或者更改现有文件的信息。对于文件创建,如果将该参数指定为nil,将会为该文件设置默认权限。fileAttributesAtPath:traverseLink:方法返回一个包含指定文件厲性的宇典。对于符号链接(symboliclink),traverseLink:参数的值为yes或no。如果该文件是一个符号链接,则指定yes,并且返回链接到的文件厲性。如果指定no,则返回链接本身的属性。对于现有的文件,属性字典包括各种信息,如文件的所有者、文件大小、文件的创建曰期,等等。字典的每个属性都可以根据其键来提取,而所有键都定义在头文件(Foundation/NSFileManager.h>中。例如,表示文件大小的键为NSFileSize。716.1管理文件和目录:NSFileManager代码清单16-1展示了一些基本的文件操作。这个例子假设当前目录中存在一个名为testfile的文件,文件的内容如下://Basicfileoperations//Assumestheexistenceofafilecalled“testfile”//inthecurrentworkingdirectory#import<Foundation/NSObject.h>#import<Foundation/NSString.h>#import<Foundation/NSFileManager.h>#import<Foundation/NSAutoreleasePool.h>#import<Foundation/NSDictionary.h>intmain(intargc,char*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];NSString*fName=@”testfile”;NSFileManager*fm;NSDictionary*attr;816.1管理文件和目录:NSFileManager//Needtocreateaninstanceofthefilemanagerfm=[NSFileManagerdefaultManager];//Let’smakesureourtestfileexistsfirstif([fmfileExistsAtPath:fName]==NO){NSLog(@”Filedoesn’texist!”);return1;}//Nowlet’smakeacopyif([fmcopyPath:fNametoPath:@”newfile”handler:nil]==NO){NSLog(@”Filecopyfailed!”);return2;}//Let’stesttoseeifthetwofilesareidenticalif([fmcontentsEqualAtPath:fNameandPath:@”newfile”]==NO){NSLog(@”Filesarenotequal!”);return3;}//Nowlet’srenamethecopyif([fmmovePath:@”newfile”toPath:@”newfile2”handler:nil]==NO){NSLog(@”Filerenamefailed!”);return4;}916.1管理文件和目录:NSFileManager//Getthesizeofnewfile2if((attr=[fmfileAttributesAtPath:@”newfile2”traverseLink:NO])==nil){NSLog(@”Couldn’tgetfileattributes!”);return5;}NSLog(@”Filesizeis%ibytes”,[[attrobjectForKey:NSFileSize]intValue]);//Andfinally,let’sdeletetheoriginalfileif([fmremoveFileAtPath:fNamehandler:nil]==NO){NSLog(@”Fileremovalfailed!”);return6;}NSLog(@”Alloperationsweresuccessful!”);//Displaythecontentsofthenewly-createdfileNSLog(@”%@”[NSStringstringWithContentsOfFile:@”newfile2”]);[pooldrain];return0;}1016.1管理文件和目录:NSFileManager程序16.1输出Filesizeis84bytesAlloperationsweresuccessful!Thisisatestfilewithsomedatainit.Here’sanotherlineofdata.Andathird.这个程序首先测试testfile文件是否存在。如果存在,则复制testfile文件,然后比较原文件和复制文件是否相等。经验丰富的UNIX用户都知道,不能只通过为方法copyPath:toPath:和movePath:toPath:指定目标目录,就将文件移动或复制到这个目录中,必须明确地指定目录中的文件名。1116.1管理文件和目录:NSFileManagermovePath:toPath方法可以用来将文件从一个目录移到另一个目录中(也可以用来移动整个目录)。如果两个路径引用同一目录中的文件(如本例所示),其结果仅仅是重新命名这个文件.因此,在代码清单16-1中,使用这个方法将文件newfile重新命名为newfile2。如表16-1所示,在执行复制、重命名或移动操作时,目标文件不能是已存在的;否则,操作将失败。newfile2的大小是通过使用fileAttributesAtPath:taverseLink:方法确定的。测试并确保返回了一个非nil目录,然后使用NSDictionary类中的方法objectForKey:,并用键NSFileSize从字典中获得文件的太小。最后,显示字典中表示文件大小的整数值。程序使用removeFileAtPath:handler:方法来删除原始文件testfile。1216.1管理文件和目录:NSFileManager最后,使用NSString的stringWithContentsOfFile:方法将文件newfile2的内容读入一个宇符串对象,然后这个对象作为参数传递给要显示的NSLog。在代码清单16-1中,测试每个文件操作以检査它是否成功。如果任何一个操作失败,就会使用NSLog来记录错误,并且程序将通过返回一个非零的退出状态而退出。根据约定,每个非零值郁表示一次程序失败,并且根据错误类型,这个值都是唯一的。如果正在编写命令行工具,这将是一项有用的技术,因为可以由另一个程序来测试返回值,比如从一个shell脚本中测试。1316.1.1使用NSData类使用文件时,需要频繁的将数据读入一个临时存储区,它通常称为缓冲区。当收集数据,一遍随后将这些数据输出到文件中,通常也使用储存区。Foundation的NSData类提供了一种简单的方式,它用来设置缓冲区,将文件的内容读入缓冲区,或将缓冲区的内容写到一个文件。有一点不要奇怪,对于32位应用程序,NSDATA缓冲区最多可存储2GB的数据。对于64位应用程序,最多可存储8EB的数据。正如你所期望的,我们既可以定义不变缓冲区,也可以定义可变的缓冲区。14.16.1.1使用NSData类正如你所期望的,我们既可以定义不可变缓冲区(使用NSData类),也可以定义可变的缓冲区(使用NSMutableData类)。在本章和后续几章将介绍这个类的方法。代码清单16-2展示了如何方便地将文件的内容读入内存缓冲区。这个程序读取文件newfile2的内容,并将其写人一个名为newfile3的新文件中。从某种意义来说,它实现了文件的复制操作,尽管它采取的方式并不像方法copyPath:toPath:handler那样直接。1516.1.1使用NSData类代码清单16-2//Makeacopyofafile#import<Foundation/NSObject.h>#import<Foundation/NSString.h>#import<Foundation/NSFileManager.h>#import<Foundation/NSAutoreleasePool.h>#import<Foundation/NSData.h>intmain(intargc,char*argv[]){ NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init]; NSFileManager*fm; NSData*fileData; fm=[NSFileManagerdefaultManager]; //Readthefilenewfile2 fileData=[fmcontentsAtPath:@”newfile2”]; if(fileData==nil){ NSLog(@”Filereadfailed!”); return1; } //Writethedatatonewfile3 if([fmcreateFileAtPath:@”newfile3”contents:fileData attributes:nil]==NO){ NSLog(@”Couldn’tcreatethecopy!”); return2; } NSLog(@”Filecopywassuccessful!”); [pooldrain]; return0;}1616.1.1使用NSData类程序16.2输出:Filecopywassuccessful!NSData的ccmtentsAtPath:方法仅仅接受一个路径名,并将指定文件的内容读人该方法创建的存储区,如果读取成功,这个方法将返回存储区对象作为结果,否则(例如,该文件不存在或者你不能读取),将返回nil。方法createFUeAtPath:contents:attributes:创建了一个具有特定属性(或者如果attributes参数提供为nil,则采用默认的属性值)的文件。然后,将指定的NSData对象内容写入这个文件中,在本例中,数据区包含前面读取的文件内容。1716.1.2使用目录表16-2总结了NSFileManager提供的用于处理目录的一些方法。其中大多数方法和用于普通文件的方法相同,如表16-1所示。18.16.1.2使用目录代码清单16-3展示了一些使用目录的基本操作。//Somebasicdirectoryoperations#import<Foundation/NSObject.h>#import<Foundation/NSString.h>#import<Foundation/NSFileManager.h>#import<Foundation/NSAutoreleasePool.h>intmain(intargc,char*argv[]){ NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init]; NSString*dirName=@”testdir”; NSString*path; NSFileManager*fm; //Needtocreateaninstanceofthefilemanager fm=[NSFileManagerdefaultManager]; //Getcurrentdirectory path=[fmcurrentDirectoryPath]; NSLog(@”Currentdirectorypathis%@”,path); //Createanewdirectory1916.1.2使用目录if([fmcreateDirectoryAtPath:dirNameattributes:nil]==NO){ NSLog(@”Couldn’tcreatedirectory!”); return1;}//Renamethenewdirectoryif([fmmovePath:dirNametoPath:@”newdir”handler:nil]==NO){ NSLog(@”Directoryrenamefailed!”); return2;}//Changedirectoryintothenewdirectoryif([fmchangeCurrentDirectoryPath:@”newdir”]==NO){ NSLog(@”Changedirectoryfailed!”); return3;}//Nowgetanddisplaycurrentworkingdirectorypath=[fmcurrentDirectoryPath];NSLog(@”Currentdirectorypathis%@”,path);NSLog(@”Alloperationsweresuccessful!”);[pooldrain];return0;}2016.1.2使用目录程序16-3输出:Currentdirectorypathis/Users/stevekochan/progs/ch16Currentdirectorypathis/Users/stevekochan/progs/ch16/newdirAlloperationsweresuccessful!2116.1.2使用目录代码清单16-3很容易理解。出于获得信息的目的,首先获取当前的目录路径,然后,在当前目彔中创建一个名为testdir的新目录。然后使用movePath:toPath:handler方法将新目录testdir重命名为newdir。记住,这个方法还可以用来将整个目录结构(这意味着包括目录的内容)从文件系统的一个位置移动到另一个位置。重命名新目录之后,程序使用changeCurrentDirectoryPath:方法将这个新目录设置为当前目录。然后,显示当前目录路径,以验证修改是否成功。2216.1.3

枚举目录中的内容有时候需要获得目录的内容列表。使用enumeratorAtPath:方法或者directoryContentsAtPath:方法,都可以完成枚举过程。如果使用第一种方法,一次可以枚举指定目录中的每个文件,默认情况下,如果其中一个文件为目录,那么也会递归枚举它的内容。在这个过程中,通过像枚举对象发送一条skipDescendants消息,可以动态的阻止递归过程,从而不再枚举目录中的内容。对于directoryContentsAtPath:方法,使用这个方法。可以枚举指定目录的内容,并在一个数组中返回文件列表。如果这个目录中的任何文件本身是个目录,这个方法并不递归枚举它的内容。23.16.1.3

枚举目录中的内容代码清单16-4演示了如何在程序中使用这两个方法。#import<Foundation/NSString.h>#import<Foundation/NSFileManager.h>#import<Foundation/NSAutoreleasePool.h>#import<Foundation/NSArray.h>intmain(intargc,char*argv[]){ NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init]; NSString*path; NSFileManager*fm; NSDirectoryEnumerator*dirEnum; NSArray*dirArray; //Needtocreateaninstanceofthefilemanager fm=[NSFileManagerdefaultManager]; //Getcurrentworkingdirectorypath path=[fmcurrentDirectoryPath]; //Enumeratethedirectory dirEnum=[fmenumeratorAtPath:path]; NSLog(@”Contentsof%@:”,path); while((path=[dirEnumnextObject])!=nil) NSLog(@”%@”,path); //Anotherwaytoenumerateadirectory dirArray=[fmdirectoryContentsAtPath: [fmcurrentDirectoryPath]]; NSLog(@”ContentsusingdirectoryContentsAtPath:”); for(pathindirArray) NSLog(@”%@”,path); [pooldrain]; return0;}2416.1.3

枚举目录中的内容程序16-4输出:Contentsof/Users/stevekochan/mysrc/ch16:a.outdir1.mdir2.mfile1.mnewdirnewdir/file1.mnewdir/outputpath1.mtestfileContentsusingdirectoryContentsAtPath:a.outdir1.mdir2.mfile1.mnewdirpath1.mtestfile2516.1.3

枚举目录中的内容让我们仔细看看以下代码内容:dirEnum=[fmenumeratorAtPath:path];NSLog(@”Contentsof%@:”,path;while((path=[dirEnumnextObject])!=nil)NSLog(@”%@”,path); 通过向文件管理器对象(此处是fm)发送enumeratorAtPath:消息来开始目录的枚举过程。enumeratorAtPath:方法返回了一个NSDirectortyEnumerator对象,这个对象存储在dirEnum中。现在,毎次向该对象发送nextObject消息时,都会返回所枚举的目录中下一个文件的路径。没有其他文件可供枚举过程使用时,会返回nil。 从代码清单16-4的输出中,可以看到这两种枚举技术的不同之处。enumeratorAtPath:方法列出了newdir目录中的内容,而方法directoryContentsAtPath:没有。如果newdir包含子目录,那么方法enumeratorAtPath:也会枚举其中的内容。

2616.1.3

枚举目录中的内容前面提到过,在代码清单16-4中while循环的执行过程中,通过对代码做如下更改,可以阻止任何子目录中的枚举。

while((path=[dirEnumnextObject])!=nil){ NSLog(@”%@”,path); [fmfileExistsAtPath:pathisDirectory:&flag]; if(flag==YES) [dirEnumskipDescendents]; }2716.1.3

枚举目录中的内容这里,flag是一个BOOL变量。如果指定的路径是目录,则fileExistsAtPath:在flag中存储yes,否则存储NO。另外提醒一下,无需像在这个程序中那样进行快速枚举,使用以下NSLog调用可显示整个dirArray的内容:

NSLog(“%@”,dirArray);2816.2使用路径:NSPathUtilities.hNSPathUtilities.h包含了NSString的函数和分类扩展,它允许你操作路径名。应该尽可能的使用这些函数,以便使程序更独立于文件系统结构以及特定文件和目录的位置。代码清单16-5展示了如何使用NSPathUtilities.h提供的几种函数和方法。29.16.2使用路径:NSPathUtilities.h//Somebasicpathoperations#import<Foundation/NSString.h>#import<Foundation/NSArray.h>#import<Foundation/NSFileManager.h>#import<Foundation/NSAutoreleasePool.h>#import<Foundation/NSPathUtilities.h>intmain(intargc,char*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];NSString*fName=@”path.m”;NSFileManager*fm;NSString*path,*tempdir,*extension,*homedir,*fullpath;NSString*upath=@”~stevekochan/progs/../ch16/./path.m”;NSArray*components;fm=[NSFileManagerdefaultManager];//Getthetemporaryworkingdirectorytempdir=NSTemporaryDirectory();NSLog(@”TemporaryDirectoryis%@”,tempdir);//Extractthebasedirectoryfromcurrentdirectorypath=[fmcurrentDirectoryPath];NSLog(@”Basediris%@”,[pathlastPathComponent]);//CreateafullpathtothefilefNameincurrentdirectoryfullpath=[pathstringByAppendingPathComponent:fName];NSLog(@”fullpathto%@is%@”,fName,fullpath);3016.2使用路径:NSPathUtilities.h//Getthefilenameextensionextension=[fullpathpathExtension];NSLog(@”extensionfor%@is%@”,fullpath,extension);//Getuser’shomedirectoryhomedir=NSHomeDirectory();NSLog(@”Yourhomedirectoryis%@”,homedir);//Divideapathintoitscomponentscomponents=[homedirpathComponents];for(pathincomponents)NSLog(@”%@”,path);//“Standardize”apathNSLog(@”%@=>%@”,upath,[upathstringByStandardizingPath]);[pooldrain];return0;}输出:TemporaryDirectoryis/var/folders/HT/HTyGLvSNHTuNb6NrMuo7QE+++TI/-Tmp-/Basedirisexamplesfullpathtopath.mis/Users/stevekochan/progs/examples/path.mextensionfor/Users/stevekochan/progs/examples/path.mismYourhomedirectoryis/Users/stevekochan/Usersstevekochan~stevekochan/progs/../ch16/./path.m=>~stevekochan/ch16/path.m3116.2使用路径:NSPathUtilities.h函数NSTemporaryDirectory返回系统中可以用来创建临时文件的目录路径名。函数lastPathComponent用来从路径中提取最后一个文件名。函数StringByAppendingPathCompent方法用于将文件名附加到路径的末尾。函数PathExtension方法给出了指定路径名的文件扩展名。函数NSHomeDirectory返回当前用户的主目录函数PathCompentents返回一个数组,包含指定路径的每个组成部分32.16.2.1常用的路径处理方法33.16.2.1常用的路径处理方法

34.16.2.2复制文件和使用NSProcessInfo类

35.36.16.3基本的文件操作:NSFileHandle利用NSFileHandle类提供的方法,允许更有效的使用文件。一般而言,我们处理文件时都要经历以下三个步骤:1.打开文件,并获取一个NSFileHandle对象,以便在后面的I/O才做中引用该文件2.对打开的文件执行I/O操作3.关闭文件37.16.3基本的文件操作:NSFileHandle

38.16.3基本的文件操作:NSFileHandle上表中并未列出获取NSFileHandle以用于标准输人、标准输出、标准错误和空设备的方法。它们的格式为fileHandleWithDevice,其中Device可以是Standardlnput、StandardOutput,StandardError或NullDevice。这里没有列出用干后台(也就是,异步)读取和写入的方法。应该注意到FileHandle类并没有提供创建文件的功能.前面描述过,必须使用FileManager方法来创建文件。因此,方法filsHawdleFofWritingAtPath;和fileHandkForUpdatingAtPath:都假定文件已存在,否则返回nil。对于这两个方法,文件的偏移董都设为文件的开始,所以都是在文件的开始位置开始写人(或更新模式的读取)。另外,如果在UNIX系统下编程应该注意,打开用于读取的文件,不要截断文件I如果想要这么做,不得不自己完成这项操作A代码清单16-7打开本章开始创建的原始testfile文件,读取它的内容,并将其复制到名为testout的文件中。3916.3基本的文件操作:NSFileHandle//Somebasicfilehandleoperations//Assumestheexistenceofafilecalled“testfile”//inthecurrentworkingdirectory#import<Foundation/NSObject.h>#import<Foundation/NSString.h>#import<Foundation/NSFileHandle.h>#import<Foundation/NSFileManager.h>#import<Foundation/NSAutoreleasePool.h>#import<Foundation/NSData.h>intmain(intargc,char*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];NSFileHandle*inFile,*outFile;NSData*buffer;//OpenthefiletestfileforreadinginFile=[NSFileHandlefileHandleForReadingAtPath:@”testfile”];if(inFile==nil){NSLog(@”Openoftestfileforreadingfailed”);return1;}//Createtheoutputfilefirstifnecessary[[NSFileManagerdefaultManager]createFileAtPath:@”testout”contents:nilattributes:nil];//NowopenoutfileforwritingoutFile=[NSFileHandlefileHandleForWritingAtPath:@”testout”];if(outFile==nil){NSLog(@”Openoftestoutforwritingfailed”);return2;}4016.3基本的文件操作:NSFileHandle//Truncatetheoutputfilesinceitmaycontaindata[outFiletruncateFileAtOffset:0];//ReadthedatafrominFileandwriteittooutFilebuffer=[inFilereadDataToEndOfFile];[outFilewriteData:buffer];//Closethetwofiles[inFilecloseFile];[outFilecloseFile];//Verifythefile’scontentsNSLog(@”%@”,[NSStringStringWithContentOfFile:@”testout”]);[pooldrain];return0;}输出:Thisisatestfilewithsomedatainit.Here’sanotherlineofdata.Andathird.4116.3基本的文件操作:NSFileHandle方法readDataToEndOfFile:毎次从文件中读取最多UINT_MAX个字节的数据,这个量定义在头文件<limits.h>中,并且在许多系统中值等于FFFFFFFF16。这个值对于你编写的任何应用程序而言,已经足够大了。还可以中断这项操作,以执行少量读取和写入。利用方法readDataOfLength:甚至可以设置循环,一次在文件之间传输一缓冲区的字节。缓冲区的大小可能是8192(8Kb)字节,.也可以是131072(128Kb)字节,经常使用的是2的乘方,这是因为底层的操作系统通常以块为单位执行I/O操作的,而块的大小一般为2的乘方个字节a可能要在系统上试用不同的值,以查看哪个值最适合。如果读取方法到达文件的末尾,并且没有读到任何数据,那么这个方法将返回一个空的NSData对象(也就是,缓冲区中没有字节)。可以对这个缓冲区应用length方法,并测试长度是否等于零,以查看该文件中是否还剩有数据可以读取。4216.3基本的文件操作:NSFileHandle如果打开一个要更新的文件,则文件的偏移量要被设为文件的开始。通过在文件中定位(seeking),可以更改偏移量,然后执行该文件的读写操作因此,要定位到文件(文件的句柄为databaseHandle)的第10个字节,可以编写如下消息表达式:[databaseHandleseekToFileOffset:10];通过获得当前的文件偏移4,然后加上或者减去这个值,就得到相对文件位置。因此,要跳过文件中当前位置之后的128个字节,编写如下代码:[databaseHandleseekToFileOffet:[databaseHandleoffsetInFile]+128];要

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论