16.1.3 枚举目录中的内容

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

对于directoryContentsAtPath:方法,使用这个方法,可以枚举指定目录的内容,并在一个数组中返回文件列表。如果这个目录中的任何文件本身是个目录,这个方法并不递归枚举它的内容。

代码清单16-4演示了如何在程序中使用这两个方法。

代码清单16-4


//Enumerate the contents of a directory

import<Foundation/NSString.h>

import<Foundation/NSFileManager.h>

import<Foundation/NSAutoreleasePool.h>

import<Foundation/NSArray.h>

int main(int argc, char*argv[])

{

NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];

NSString*path;

NSFileManager*fm;

NSDirectoryEnumerator*dirEnum;

NSArray*dirArray;

//Need to create an instance of the file manager

fm=[NSFileManager defaultManager];

//Get current working directory path

path=[fm currentDirectoryPath];

//Enumerate the directory

dirEnum=[fm enumeratorAtPath:path];

NSLog(@“Contents of%@:,path);

while((path=[dirEnum nextObject])!=nil)

NSLog(@,path);

//Another way to enumerate a directory

dirArray=[fm directoryContentsAtPath:

[fm currentDirectoryPath]];

NSLog(@“Contents using directoryContentsAtPath:);

for(path in dirArray)

NSLog(@,path);

[pool drain];

return 0;

}


代码清单16-4输出


Contents of/Users/stevekochan/mysrc/ch16:

a.out

dir1.m

dir2.m

file1.m

newdir

newdir/file1.m

newdir/output

path1.m

testfile

Contents using directoryContentsAtPath:

a.out

dir1.m

dir2.m

file1.m

newdir

path1.m

testfile


让我们仔细看看以下代码内容:


dirEnum=[fm enumeratorAtPath:path];

NSLog(@“Contents of%@:,path);

while((path=[dirEnum nextObject])!=nil)

NSLog(@,path);


通过向文件管理器对象(此处是fm)发送enumeratorAtPath:消息来开始目录的枚举过程。enumeratorAtPath:方法返回了一个NSDirectortyEnumerator对象,这个对象存储在dirEnum中。现在,每次向该对象发送nextObject消息时,都会返回所枚举的目录中下一个文件的路径。没有其他文件可供枚举过程使用时,会返回nil。

从代码清单16-4的输出中,可以看到这两种枚举技术的不同之处。enumeratorAtPath:方法列出了newdir目录中的内容,而方法directoryContentsAtPath:没有。如果newdir包含子目录,那么方法enumeratorAtPath:也会枚举其中的内容。

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


while((path=[dirEnum nextObject])!=nil){

NSLog(@,path);

[fm fileExistsAtPath:path isDirectory:&flag];

if(flag==YES)

[dirEnum skipDescendents];

}


这里,flag是一个BOOL变量。如果指定的路径是目录,则fileExistsAtPath:在flag中存储yes,否则存储NO。

另外提醒一下,无需像在这个程序中那样进行快速枚举,使用以下NSLog调用可显示整个dirArray的内容:

NSLog(@,dirArray);