How to check if a file exists in the Documents directory in Swift?

IosXcodeSwift

Ios Problem Overview


How to check if a file exists in the Documents directory in Swift?

I am using [ .writeFilePath ] method to save an image into the Documents directory and I want to load it every time the app is launched. But I have a default image if there is no saved image.

But I just cant get my head around how to use the [ func fileExistsAtPath(_:) ] function. Could someone give an example of using the function with a path argument passed into it.

I believe I don't need to paste any code in there as this is a generic question. Any help will be much appreciated.

Cheers

Ios Solutions


Solution 1 - Ios

Swift 4.x version

    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 version

    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 version, need to use 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")
    }

Solution 2 - Ios

Check the below code:

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");
}

Solution 3 - Ios

Nowadays (2016) Apple recommends more and more to use the URL related API of NSURL, NSFileManager etc.

To get the documents directory in iOS and Swift 2 use

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

The try! is safe in this case because this standard directory is guaranteed to exist.

Then append the appropriate path component for example an sqlite file

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

Now check if the file exists with checkResourceIsReachableAndReturnError of NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

If you need the error pass the NSError pointer to the parameter.

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 is marked as can throw

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

To consider only the boolean return value and ignore the error use the nil-coalescing operator

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

Solution 4 - Ios

It's pretty user friendly. Just work with NSFileManager's defaultManager singleton and then use the fileExistsAtPath() method, which simply takes a string as an argument, and returns a Bool, allowing it to be placed directly in the if statement.

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!!
}

Note that the downcast to String isn't necessary in Swift 2.

Solution 5 - Ios

Swift 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;
        }
    }
}

Using: -

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

Solution 6 - Ios

works at 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)
    }

where "userInfo" - file's name, and "sqlite3" - file's extension

Solution 7 - Ios

An alternative/recommended Code Pattern in Swift 3 would be:

  1. Use URL instead of FileManager

  2. Use of exception handling

    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)")
        }
    }
    

Solution 8 - Ios

Very simple: If your path is a URL instance convert to string by 'path' method.

    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
        }
    }

Solution 9 - Ios

For the benefit of Swift 3 beginners:

  1. Swift 3 has done away with most of the NextStep syntax
  2. So NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain are no longer used
  3. Instead use URL and FileManager
  4. NSSearchPathForDirectoriesInDomain is not needed
  5. Instead use FileManager.default.urls

Here is a code sample to verify if a file named "database.sqlite" exists in application document directory:

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)")
    }
    
}

Solution 10 - Ios

Swift 5

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

Solution 11 - Ios

This works fine for me in 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
        
        }
    
    
}

You can check with this call:

   if existingFile(fileName: "yourfilename") == true {

            // your code if file exists

           } else {

           // your code if file does not exist

           }

I hope it is useful for someone. @;-]

Solution 12 - Ios

You must add a "/" slash before filename, or you get path like ".../DocumentsFilename.jpg"

Solution 13 - Ios

Swift 4 example:

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)
}

I put the check in my loadData function which I called in viewDidLoad.

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

Then I defined loadData below.

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...")
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGgnDpSinghView Question on Stackoverflow
Solution 1 - Iosmike.tihonchikView Answer on Stackoverflow
Solution 2 - IosPREMKUMARView Answer on Stackoverflow
Solution 3 - IosvadianView Answer on Stackoverflow
Solution 4 - IosMick MacCallumView Answer on Stackoverflow
Solution 5 - IosLakhdeep SinghView Answer on Stackoverflow
Solution 6 - IosnastassiaView Answer on Stackoverflow
Solution 7 - IosSurya Kameswara Rao RaviView Answer on Stackoverflow
Solution 8 - IosRohit SisodiaView Answer on Stackoverflow
Solution 9 - IosSurya Kameswara Rao RaviView Answer on Stackoverflow
Solution 10 - IosAlessandro OrnanoView Answer on Stackoverflow
Solution 11 - IosMaurizio FIORINOView Answer on Stackoverflow
Solution 12 - IosJauzeeView Answer on Stackoverflow
Solution 13 - IosJoshua DanceView Answer on Stackoverflow