Rol*_*ien 7 macos cocoa objective-c
这是在Mac上:
如果我有两个文件名/ foo/foo和/ foo/FOO,它们可能引用相同的文件,或者可能是不同的文件,具体取决于文件系统.我怎么弄清楚它们是否都指向同一个文件?如果是,我如何获得文件名的正确表示?
我的问题是由链接引起的.链接可能指向/ foo/FOO,但实际目录名为/ foo/foo.
是否有任何函数将跟随链接并给我链接文件的完整路径?[NSFileManager pathContentOfSymbolicLinkAtPath]给出可能处于不正确情况的相对路径.
最终我要做的是缓存文件的信息.但是如果我有两个不同的路径用于同一个文件,我的缓存可能会失去同步.
谢谢
TAL*_*ama 15
你的问题确实有几个不同的部分.通过我的阅读,你想要:
1一种判断两个不同路径是否是同一磁盘文件的方法
2磁盘上文件的规范名称,带有正确的外壳
还有第三个问题与显示名称有关,因为在OS X中,文件可以本地化其名称,并且对于不同的语言环境显示不同.所以让我们补充一下
3获取显示名称的方法,因为我们可能希望根据用户查看文件系统的方式来缓存内容,而不是文件系统在终端中的显示方式.
我们可以用@ boaz-stuller指出的FSRef技巧来解决1.或者这里有一些代码使用更高级别的Cocoa调用来完成它,这为我们节省了一些内存(因为我们可以让它NSAutoreleasePool为我们做):
long getInode(NSString* path) {
NSFileManager* fm = [NSFileManager defaultManager];
NSError* error;
NSDictionary* info = [fm attributesOfItemAtPath:path error:&error];
NSNumber* inode = [info objectForKey:NSFileSystemFileNumber];
return [inode longValue];
}
Run Code Online (Sandbox Code Playgroud)
但要解决2,我们必须使用FSRefs来找出文件的规范框:
NSString* getActualPath(NSString* path) {
FSRef ref;
OSStatus sts;
UInt8* actualPath;
//first get an FSRef for the path
sts = FSPathMakeRef((const UInt8 *)[path UTF8String], &ref, NULL);
if (sts) return [NSString stringWithFormat:@"Error #%d making ref.", sts];
//then get a path from the FSRef
actualPath = malloc(sizeof(UInt8)*MAX_PATH_LENGTH);
sts = FSRefMakePath(&ref, actualPath, MAX_PATH_LENGTH);
if (sts) return [NSString stringWithFormat:@"Error #%d making path.", sts];
return [NSString stringWithUTF8String:(const char*)actualPath];
}
Run Code Online (Sandbox Code Playgroud)
这一点都不错,但是当我们用Cocoa方法解决3时我们仍然很高兴:
NSString* getDisplayPath(NSString* path) {
NSFileManager* fm = [NSFileManager defaultManager];
NSString* mine = [fm displayNameAtPath:path];
NSString* parentPath = [path stringByDeletingLastPathComponent];
NSString* parents = [@"/" isEqualToString:parentPath]
? @""
: getDisplayPath(parentPath);
return [NSString stringWithFormat:@"%@/%@", parents, mine];
}
Run Code Online (Sandbox Code Playgroud)
最后,我们可以添加一些驱动程序代码并将它们整合到一个CoreFoundation命令行工具中(我必须添加AppKit框架才能进行编译).
NSString* fileInfoString(NSString* path) {
long inode = getInode(path);
return [NSString stringWithFormat:
@"\t%@ [inode #%d]\n\t\tis actually %@\n\t\tand displays as %@",
path,
inode,
getActualPath(path),
getDisplayPath(path)];
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
if (argc < 2) {
NSLog(@"Usage: %s <path1> [<path2>]", argv[0]);
return -1;
}
NSString* path1 = [NSString stringWithCString:argv[1]];
NSString* path2 = argc > 2
? [NSString stringWithCString:argv[1]]
: [path1 uppercaseString];
long inode1 = getInode(path1);
long inode2 = getInode(path2);
NSString* prefix = [NSString stringWithFormat:
@"Comparing Files:\n%@\n%@",
fileInfoString(path1),
fileInfoString(path2)];
int retval = 0;
if (inode1 == inode2) {
NSLog(@"%@\nSame file.", prefix);
} else {
NSLog(@"%@\nDifferent files.", prefix);
retval = 1;
}
[pool drain];
return retval;
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以将它们放在一起并运行它:
$ checkpath /users/tal
2008-12-15 23:59:10.605 checkpath[22375:10b] Comparing Files:
/users/tal [inode #1061692]
is actually /Users/tal
and displays as /Users/tal
/USERS/TAL [inode #1061692]
is actually /Users/tal
and displays as /Users/tal
Same file.
FSPathMakeRef()在两个路径上使用,然后使用FSCompareFSRefs()它们来查看它们是否是同一个文件/文件夹.然后,您可以使用FSRefMakePath()获取规范表示,但如果您向用户显示文件名,则应使用NSFileManager's- displayNameAtPath:方法,因为它可以正确处理本地化和显示/隐藏扩展.
| 归档时间: |
|
| 查看次数: |
1813 次 |
| 最近记录: |