16.2.2 复制文件和使用NSProcessInfo类

代码清单16-6说明了如何使用命令行工具来实现简单的文件复制操作。这个命令的用法如下:copy from-file to-file

与NSFileManager的copyPath:toPath:handler:方法不同,命令行工具允许to-file是目录名。在这个例子中,文件以名称from-file被复制到to-file目录中;与copyPath:toPath:handler:方法不同的还有,如果to-file目录已存在,允许重写其内容。这更像标准UNIX的复制命令cp。

通过在main函数中使用argv和argc参数,可以从命令行中获得文件名。这两个参数分别包括了命令行上键入的参数个数(包括命令名),以及指向C风格字符串数组的指针。

并非必须处理C字符串(使用argv参数时,必须处理c字符串),而是利用Foundation中的类NSProcessInfo。NSProcessInfo类中包含一些方法,它们允许你设置或检索正在运行的应用程序(即进程)的各种类型的信息。表16-5总结了这些方法。

16.2.2 复制文件和使用NSProcessInfo类 - 图1

代码清单16-6


//Implement a basic copy utility

import<Foundation/NSString.h>

import<Foundation/NSArray.h>

import<Foundation/NSFileManager.h>

import<Foundation/NSAutoreleasePool.h>

import<Foundation/NSPathUtilities.h>

import<Foundation/NSProcessInfo.h>

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

{

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

NSFileManager*fm;

NSStringsource,dest;

BOOL isDir;

NSProcessInfo*proc=[NSProcessInfo processInfo];

NSArray*args=[proc arguments];

fm=[NSFileManager defaultManager];

//Check for two arguments on the command line

if([args count]!=3){

NSLog(@“Usage:%@src dest”,[proc processName]);

return 1;

}

source=[args objectAtIndex:1];

dest=[args objectAtIndex:2];

//Make sure the source file can be read

if([fm isReadableFileAtPath:source]==NO){

NSLog(@“Cant read%@”,source);

return 2;

}

//See if the destination file is a directory

//if it is, add the source to the end of the destination

[fm fileExistsAtPath:dest isDirectory:&isDir];

if(isDir==YES)

dest=[dest stringByAppendingPathComponent:

[source lastPathComponent]];

//Remove the destination file if it already exists

[fm removeFileAtPath:dest handler:nil];

//Okay, time to perform the copy

if([fm copyPath:source toPath:dest handler:nil]==NO){

NSLog(@“Copy failed!”);

return 3;

}

NSLog(@“Copy of%@to%@succeeded!”,source, dest);

[pool drain];

return 0;

}


代码清单16-6输出

$Is-l see what files we have

total 96

-rwxr-xr-x 1 stevekoc staff 19956 Jul 24 14:33 copy

-rw-r—r—1 stevekoc staff 1484 Jul 24 14:32 copy.m

-rw-r—r—1 stevekoc staff 1403 Jul 24 13:00 file1.m

drwxr-xr-x 2 stevekoc staff 68 Jul 24 14:40 newdir

-rw-r—r—1 stevekoc staff 1567 Jul 24 14:12 path1.m

-rw-r—r—1 stevekoc staff 84 Jul 24 13:22 testfile

$copy try with no args

Usage:copy src dest$copy foo copy2

Cant read foo

$copy copy.m backup.m

Copy of copy.m to backup.m succeeded!

$diff copy.m backup.m compare the files

$copy copy.m newdir try copy into directory

Copy of copy.m to newdir/copy.m succeeeded!

$Is-l newdir

total 8

-rw-r—r—1 stevekoc staff 1484 Jul 24 14:44 copy.m

$


NSProcessInfo类中的argments方法返回一个字符串对象数组。数组的第一个元素是进程名称;其余的元素是在命令行键入的参数。

首先检查,以确保在命令行键入这两个参数。这是通过测试数组args的大小实现的,这个数组是从方法arguments返回的。如果测试成功,那么程序将从数组args中提取源文件名和目标文件名,并将它们的值分别赋给source和test。

然后程序测试源文件是否能够读取。如果不能,则生成一条出错消息,并退出程序。

语句


[fm fileExistsAtPath:dest isDirectory:&isDir];


检查dest指定的文件是否是目录。前面讲过,答案YES或NO将存储到变量isDir中。

如果dest是目录,则要将源文件名的最后一部分附加到dest目录名的末尾,使用路径工具方法stringByAppendingPathComponent:来实现这个功能。因此,如果Source的值是ch16/copy1.m, dest的值是/Users/stevekochan/progs,并且后者是个目录,那么dest的值将更改为/Users/stevekochan/progs/copy1.m。

方法copyPath:ToPath:handler:不容许重写文件。因此,要避免错误,程序尝试用方法removeFileAtPath:handler:来删除目标文件。没有必要担心这个方法能否成功;因为如果目标文件不存在,它将失败。

到达程序末尾时,可以假设程序的所有部分都运行良好,并为此生成一条消息。