ChatGPT解决这个技术问题 Extra ChatGPT

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

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


m
mike.tihonchik

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

It looks like the answer was updated so the absoluteString comments seem obsolete.
presumably those comments were that absoluteString doesn't work from a URL, but path does, which is what I found!
is the same logic when searching for file in .libraryDirectory? I ask because I tried and it cannot find it, even if the file was successfully written into it.
k
keithbhunter

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

@SaqibOmer try casting paths as NSString rather than String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
@PREMKUMAR Why that strange string interpolation? You could use absoluteString to convert NSURL to path but it would be better to just keep the path as a string (NSString) like you do in Swift 1.2.
I found this answer to work properly with Swift 2: stackoverflow.com/a/36897617/1245231
v
vadian

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

I think in Swift 3 this is now checkResourceIsReachable() and just returns Bool for URL type.
The problem I found is that you never seem to get a "false" value from checkResourceIsReachable() in Swift3, just an exception if the file is not there. I'm not very happy using an API where a lot of calls will result in an exception instead of a simple return value.
@KendallHelmstetterGelner Swift's try - catch pattern does not throw exceptions. It's not comparable with exceptions in Objective-C. It's an efficient error handling system.
It's more efficient I know, but conceptually I do not like it. I don't mind something throwing an exception for - an exception. But a file not existing is NOT an exception. It is a common case and should result in a false return value, not some kind of aberration with a wrapped Error object that had to be created. It may not seem like much but if you have tens of thousands of files to check the burden is too high.
M
Mick MacCallum

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.


♦ please help me here stackoverflow.com/questions/31503283/… . I don't know which code need to write.
L
Lakhdeep Singh

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
   }

n
nastassia

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


S
Surya Kameswara Rao Ravi

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

Use URL instead of FileManager 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)") } }


R
Rohit Sisodia

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

A
Alessandro Ornano

Swift 5

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

S
Surya Kameswara Rao Ravi

For the benefit of Swift 3 beginners:

Swift 3 has done away with most of the NextStep syntax So NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain are no longer used Instead use URL and FileManager NSSearchPathForDirectoriesInDomain is not needed 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)")
    }

}

A
Alex Bravo

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. @;-]


What if the user do not want to just only check the document directory? and want to search a generic path
J
Jauzee

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


J
Joshua Dance

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