【问题标题】:Testing file existence using NSURL使用 NSURL 测试文件是否存在
【发布时间】:2010-12-28 00:25:53
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: cocoa osx-snow-leopard nsurl core-foundation nsfilemanager


    【解决方案1】:

    NSURL 确实有这个方法:

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

    which "返回是否可以访问文件 URL 指向的资源。"

    NSURL *theURL = [NSURL fileURLWithPath:@"/Users/elisevanlooij/nonexistingfile.php" 
                   isDirectory:NO];
    NSError *err;
    if ([theURL checkResourceIsReachableAndReturnError:&err] == NO)
        [[NSAlert alertWithError:err] runModal];
    

    【讨论】:

    • 致任何被这个答案吓跑的 iPhone OS 开发者:checkResourceIsReachableAndReturnError: 仅在 10.6 及更高版本中可用,而在 iPhone SDK 中尚不可用。
    • 更新:iOS 4 开始提供。
    • XCode 3.2.5(支持 iOS 4.2)中的 iOS 文档状态:“此方法在 iOS 中未实现,因此不执行任何操作。”
    • 另一个更新......它在 iOS4 中没有执行任何操作,但显然它现在在 iOS5.0 的 iPhone 上受支持
    • 谁给这个函数起名了?
    【解决方案2】:

    在 iOS 上我找不到任何其他方式...

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"file.type"];
    if ([[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {...}
    

    【讨论】:

      【解决方案3】:

      这是 Swift 2 答案:

      var error:NSError?
      let folderExists = theURL.checkResourceIsReachableAndReturnError(&error)
      

      【讨论】:

      • 它应该是checkResourceIsReachable()->Void 并抛出异常,但是,你所说的对于 Xcode 7.x 是正确的
      • *抛出错误。 Swift 错误与 Objective-C 异常不同。语法相似,但用途不同。
      【解决方案4】:

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

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

      否则 CFURLResourceIsReachable 在标头状态下的注释:

      一个示例是定期维护 UI 状态,这取决于 关于特定文件的存在。当执行一个 诸如打开文件之类的操作,简单地尝试一下会更有效率 操作和处理故障,而不是首先检查可达性。

      【讨论】:

      • 我怀疑它很慢... NSURL 维护着一个指向它所代表的 HFS+ 文件系统条目的链接。根据 Apple 的说法,对于所有文件系统操作而言,URL 比路径快很多
      【解决方案5】:

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

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

      【讨论】:

      • 您可以将前面提到的checkResourceIsReachableAndReturnError:isFileURL 结合起来以保持正常。
      【解决方案6】:

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

      要改为获取布尔真/假值,请使用以下语法:

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

      如果您想记录错误:

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

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

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

      【讨论】:

        猜你喜欢
        • 2011-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-27
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多