【问题标题】:How to check if a file exists in the Documents directory in Swift?如何检查文件是否存在于 Swift 的 Documents 目录中?
【发布时间】:2014-08-02 14:51:13
【问题描述】:

如何检查Swift的Documents目录中是否存在文件?

我正在使用[ .writeFilePath ] 方法将图像保存到 Documents 目录中,并且我想在每次启动应用程序时加载它。但是如果没有保存的图像,我有一个默认图像。

但我就是不知道如何使用[ func fileExistsAtPath(_:) ] 函数。有人可以举一个使用传递路径参数的函数的例子吗?

我相信我不需要在其中粘贴任何代码,因为这是一个通用问题。任何帮助将不胜感激。

干杯

【问题讨论】:

    标签: ios xcode swift


    【解决方案1】:

    斯威夫特 5

    extension FileManager {
        class func fileExists(filePath: String) -> Bool {
            var isDirectory = ObjCBool(false)
            return self.default.fileExists(atPath: filePath, isDirectory: &isDirectory)
        }
    }
    

    【讨论】:

      【解决方案2】:

      Swift 5

      工作
          do {
              let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
              let fileUrl = documentDirectory.appendingPathComponent("userInfo").appendingPathExtension("sqlite3")
              if FileManager.default.fileExists(atPath: fileUrl.path) {
                  print("FILE AVAILABLE")
              } else {
                  print("FILE NOT AVAILABLE")
              }
          } catch {
              print(error)
          }
      

      其中"userInfo" - 文件名,"sqlite3" - 文件扩展名

      【讨论】:

        【解决方案3】:

        斯威夫特 4.2

        extension URL    {
            func checkFileExist() -> Bool {
                let path = self.path
                if (FileManager.default.fileExists(atPath: path))   {
                    print("FILE AVAILABLE")
                    return true
                }else        {
                    print("FILE NOT AVAILABLE")
                    return false;
                }
            }
        }
        

        使用:-

        if fileUrl.checkFileExist()
           {
              // Do Something
           }
        

        【讨论】:

          【解决方案4】:

          如今(2016)苹果越来越推荐使用NSURLNSFileManager等URL相关API。

          要在 iOS 和 Swift 2 中获取文档目录,请使用

          let documentDirectoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, 
                                           inDomain: .UserDomainMask, 
                                  appropriateForURL: nil, 
                                             create: true)
          

          try! 在这种情况下是安全的,因为这个标准目录保证存在。

          然后附加适当的路径组件,例如sqlite 文件

          let databaseURL = documentDirectoryURL.URLByAppendingPathComponent("MyDataBase.sqlite")
          

          现在用NSURLcheckResourceIsReachableAndReturnError 检查文件是否存在。

          let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)
          

          如果您需要错误,请将NSError 指针传递给参数。

          var error : NSError?
          let fileExists = databaseURL.checkResourceIsReachableAndReturnError(&error)
          if !fileExists { print(error) }
          

          Swift 3+:

          let documentDirectoryURL = try! FileManager.default.url(for: .documentDirectory, 
                                          in: .userDomainMask, 
                              appropriateFor: nil, 
                                      create: true)
          
          let databaseURL = documentDirectoryURL.appendingPathComponent("MyDataBase.sqlite")
          

          checkResourceIsReachable 被标记为可以抛出

          do {
              let fileExists = try databaseURL.checkResourceIsReachable()
              // handle the boolean result
          } catch let error as NSError {
              print(error)
          }
          

          要仅考虑布尔返回值并忽略错误,请使用 nil-coalescing 运算符

          let fileExists = (try? databaseURL.checkResourceIsReachable()) ?? false
          

          【讨论】:

          • 我认为在 Swift 3 中这现在是 checkResourceIsReachable() 并且只为 URL 类型返回 Bool
          • 我发现的问题是,您似乎从来没有从 Swift3 中的 checkResourceIsReachable() 获得“假”值,如果文件不存在则只是一个例外。我不太喜欢使用 API,因为很多调用会导致异常而不是简单的返回值。
          • @KendallHelmstetterGelner Swift 的try - catch 模式不会引发异常。它无法与 Objective-C 中的异常进行比较。这是一个高效的错误处理系统。
          • 我知道它更有效,但从概念上讲我不喜欢它。我不介意抛出异常的东西 - 异常。但是不存在的文件也不例外。这是一种常见的情况,应该导致错误的返回值,而不是与必须创建的包装的 Error 对象的某种异常。可能看起来不多,但如果你有几万个文件要检查,负担太重了。
          【解决方案5】:

          这在 swift4 中对我来说很好用:

          func existingFile(fileName: String) -> Bool {
          
              let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
              let url = NSURL(fileURLWithPath: path)
              if let pathComponent = url.appendingPathComponent("\(fileName)") {
                  let filePath = pathComponent.path
                  let fileManager = FileManager.default
                  if fileManager.fileExists(atPath: filePath) 
          
                 {
          
                  return true
          
                  } else {
          
                  return false
          
                  }
          
              } else {
          
                  return false
          
                  }
          
          
          }
          

          您可以通过此调用进行检查:

             if existingFile(fileName: "yourfilename") == true {
          
                      // your code if file exists
          
                     } else {
          
                     // your code if file does not exist
          
                     }
          

          我希望它对某人有用。 @;-]

          【讨论】:

          • 如果用户不想只检查文档目录怎么办?并想搜索通用路径
          【解决方案6】:

          Swift 4 示例:

          var filePath: String {
              //manager lets you examine contents of a files and folders in your app.
              let manager = FileManager.default
          
              //returns an array of urls from our documentDirectory and we take the first
              let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first
              //print("this is the url path in the document directory \(String(describing: url))")
          
              //creates a new path component and creates a new file called "Data" where we store our data array
              return(url!.appendingPathComponent("Data").path)
          }
          

          我将检查放入我在 viewDidLoad 中调用的 loadData 函数中。

          override func viewDidLoad() {
              super.viewDidLoad()
          
              loadData()
          }
          

          然后我在下面定义了 loadData。

          func loadData() {
              let manager = FileManager.default
          
              if manager.fileExists(atPath: filePath) {
                  print("The file exists!")
          
                  //Do what you need with the file. 
                  ourData = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as! Array<DataObject>         
              } else {
                  print("The file DOES NOT exist! Mournful trumpets sound...")
              }
          }
          

          【讨论】:

            【解决方案7】:

            Swift 4.x 版本

                let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
                let url = NSURL(fileURLWithPath: path)
                if let pathComponent = url.appendingPathComponent("nameOfFileHere") {
                    let filePath = pathComponent.path
                    let fileManager = FileManager.default
                    if fileManager.fileExists(atPath: filePath) {
                        print("FILE AVAILABLE")
                    } else {
                        print("FILE NOT AVAILABLE")
                    }
                } else {
                    print("FILE PATH NOT AVAILABLE")
                }
            

            Swift 3.x 版本

                let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
                let url = URL(fileURLWithPath: path)
            
                let filePath = url.appendingPathComponent("nameOfFileHere").path
                let fileManager = FileManager.default
                if fileManager.fileExists(atPath: filePath) {
                    print("FILE AVAILABLE")
                } else {
                    print("FILE NOT AVAILABLE")
                }
            

            Swift 2.x版本,需要使用URLByAppendingPathComponent

                let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
                let url = NSURL(fileURLWithPath: path)
                let filePath = url.URLByAppendingPathComponent("nameOfFileHere").path!
                let fileManager = NSFileManager.defaultManager()
                if fileManager.fileExistsAtPath(filePath) {
                    print("FILE AVAILABLE")
                } else {
                    print("FILE NOT AVAILABLE")
                }
            

            【讨论】:

            • 答案似乎已更新,因此 absoluteString cmets 似乎已过时。
            • 大概那些 cmets 是绝对字符串不能从 URL 工作,但路径可以,这是我发现的!
            • 在.libraryDirectory 中搜索文件的逻辑是一样的吗?我问是因为我试过了,即使文件成功写入它也找不到。
            【解决方案8】:

            很简单: 如果你的路径是一个 URL 实例,通过 'path' 方法转换为字符串。

                let fileManager = FileManager.default
                var isDir: ObjCBool = false
                if fileManager.fileExists(atPath: yourURLPath.path, isDirectory: &isDir) {
                    if isDir.boolValue {
                        //it's a Directory path
                    }else{
                        //it's a File path
                    }
                }
            

            【讨论】:

              【解决方案9】:

              Swift 3 中的替代/推荐代码模式是:

              1. 使用 URL 代替 FileManager
              2. 使用异常处理

                func verifyIfSqliteDBExists(){
                    let docsDir     : URL       = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                    let dbPath      : URL       = docsDir.appendingPathComponent("database.sqlite")
                
                    do{
                        let sqliteExists : Bool = try dbPath.checkResourceIsReachable()
                        print("An sqlite database exists at this path :: \(dbPath.path)")
                
                    }catch{
                        print("SQLite NOT Found at :: \(strDBPath)")
                    }
                }
                

              【讨论】:

                【解决方案10】:

                为了Swift 3初学者的利益:

                1. Swift 3 取消了大部分 NextStep 语法
                2. 所以不再使用 NSURL、NSFilemanager、NSSearchPathForDirectoriesInDomain 了
                3. 改为使用 URL 和 FileManager
                4. 不需要 NSSearchPathForDirectoriesInDomain
                5. 改为使用 FileManager.default.urls

                这是一个代码示例,用于验证应用程序文档目录中是否存在名为“database.sqlite”的文件:

                func findIfSqliteDBExists(){
                
                    let docsDir     : URL       = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                    let dbPath      : URL       = docsDir.appendingPathComponent("database.sqlite")
                    let strDBPath   : String    = dbPath.path
                    let fileManager : FileManager   = FileManager.default
                
                    if fileManager.fileExists(atPath:strDBPath){
                        print("An sqlite database exists at this path :: \(strDBPath)")
                    }else{
                        print("SQLite NOT Found at :: \(strDBPath)")
                    }
                
                }
                

                【讨论】:

                  【解决方案11】:

                  检查以下代码:

                  Swift 1.2

                  let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
                  
                  let getImagePath = paths.stringByAppendingPathComponent("SavedFile.jpg")
                  
                  let checkValidation = NSFileManager.defaultManager()
                  
                  if (checkValidation.fileExistsAtPath(getImagePath))
                  {
                      println("FILE AVAILABLE");
                  }
                  else
                  {
                      println("FILE NOT AVAILABLE");
                  }
                  

                  Swift 2.0

                  let paths = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
                  let getImagePath = paths.URLByAppendingPathComponent("SavedFile.jpg")
                  
                  let checkValidation = NSFileManager.defaultManager()
                  
                  if (checkValidation.fileExistsAtPath("\(getImagePath)"))
                  {
                      print("FILE AVAILABLE");
                  }
                  else
                  {
                      print("FILE NOT AVAILABLE");
                  }
                  

                  【讨论】:

                  • @SaqibOmer 尝试将路径转换为 ​​NSString 而不是 String。 var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
                  • @PREMKUMAR 为什么使用奇怪的字符串插值?您可以使用 absoluteStringNSURL 转换为 path 但最好将路径保留为字符串 (NSString),就像在 Swift 1.2 中所做的那样。
                  • 我发现这个答案可以在 Swift 2 中正常工作:stackoverflow.com/a/36897617/1245231
                  【解决方案12】:

                  它非常用户友好。只需使用 NSFileManager 的 defaultManager 单例,然后使用 fileExistsAtPath() 方法,该方法只需将字符串作为参数,并返回一个 Bool,允许将其直接放在 if 语句中。

                  let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
                  let documentDirectory = paths[0] as! String
                  let myFilePath = documentDirectory.stringByAppendingPathComponent("nameOfMyFile")
                  
                  let manager = NSFileManager.defaultManager()
                  if (manager.fileExistsAtPath(myFilePath)) {
                      // it's here!!
                  }
                  

                  请注意,在 Swift 2 中向下转换为 String 不是必需的。

                  【讨论】:

                  【解决方案13】:

                  您必须在文件名前添加一个“/”斜杠,否则您会得到类似“.../DocumentsFilename.jpg”的路径

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2023-03-14
                    • 2014-01-11
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-06-28
                    • 2011-03-16
                    • 1970-01-01
                    相关资源
                    最近更新 更多