74

Snow Leopard 引入了许多新方法来使用 NSURL 对象来引用文件,而不是路径名或核心服务的 FSRefs。

但是,有一项任务我找不到基于 URL 的方法:测试文件是否存在。我正在寻找基于 URL 的版本-[NSFileManager fileExistsAtPath:]YES与该方法一样,如果 URL 描述了任何内容,无论是常规文件、目录还是其他任何内容,它都应该返回。

我可以尝试查找各种​​资源值,但如果文件不存在,它们都不能明确保证不存在,并且其中一些(例如NSURLEffectiveIconKey)可能会很昂贵。

我可以只使用 NSFileManager's fileExistsAtPath:,但如果有更现代的方法,我更愿意使用它。

Cocoa、CF 或核心服务中是否有一个简单的方法或函数可以保证/记录告诉我给定的文件(或文件引用)URL 是否引用了存在的文件系统对象?

4

6 回答 6

143

NSURL 确实有这个方法:

- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error

其中“返回是否可以访问文件 URL 指向的资源。”

NSURL *theURL = [NSURL fileURLWithPath:@"/Users/elisevanlooij/nonexistingfile.php" 
               isDirectory:NO];
NSError *err;
if ([theURL checkResourceIsReachableAndReturnError:&err] == NO)
    [[NSAlert alertWithError:err] runModal];
于 2009-12-18T16:16:03.080 回答
30

在iOS上我找不到其他方法...

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"file.type"];
if ([[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {...}
于 2011-01-20T10:38:32.140 回答
10

这是Swift 2的答案:

var error:NSError?
let folderExists = theURL.checkResourceIsReachableAndReturnError(&error)
于 2016-01-28T20:11:27.423 回答
2

确定给定文件(或文件引用)URL 是否引用存在的文件系统对象对于远程资源而言本质上是昂贵的,此 CFURLResourceIsReachable() 和 [NSURL checkResourceIsReachableAndReturnError:] 的仅 10.6(无 iPhoneOS)api 都是同步的,即使您将使用它们,对于很多文件,您仍然会看到显着的延迟开销。

您应该做的是使用缓存实现您自己的异步检查例程,该例程分别创建有效资源列表。

否则,标头状态中 CFURLResourceIsReachable 的注释:

一个示例是定期维护 UI 状态,这取决于特定文档的存在。在执行诸如打开文件之类的操作时,简单地尝试操作并处理失败比首先检查可达性更有效。

于 2010-04-24T11:53:06.163 回答
1

因为 NSURL 可以代表更多本地文件系统,所以我认为没有一种通用方法可以以可靠的方式测试它们的存在。至少,Cocoa 基金会不包含这样的功能(据我所知)。

如果您只处理本地文件系统,我建议您创建一个类别 forNSURL或 for NSFileManager,并带有一条urlExists:消息。它将转换NSURLNSString(规范化路径),然后调用[NSFileManager fileExistsAtPath:]消息。

于 2009-12-18T12:06:35.190 回答
0

在 Swift 中,您可以使用该checkResourceIsReachable()方法,不幸的是,该方法将返回true(如果文件可访问)或抛出错误(解释为什么无法访问)。

要获取 bool true/false 值,请使用以下语法:

let exists = (try? inputFile.checkResourceIsReachable()) ?? false

如果您想记录错误:

let exists: Bool
do {
  exists = try inputFile.checkResourceIsReachable()
} catch {
  exists = false
  print(error.localizedDescription)
}

请记住,这是一项昂贵的操作,并且可能在之后立即过期(如果其他进程正在删除或卸载磁盘文件,而您正在检查它是否存在)。

一般来说,首选方法不是检查文件是否存在,而是简单地尝试读取或写入文件并在失败后处理任何错误。

于 2018-06-25T03:23:07.613 回答