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-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:来删除目标文件。没有必要担心这个方法能否成功;因为如果目标文件不存在,它将失败。
到达程序末尾时,可以假设程序的所有部分都运行良好,并为此生成一条消息。