Come verificare se esiste un file nella directory Documents in Swift?


127

Come verificare se esiste un file nella directory Documents in Swift?

Sto usando il [ .writeFilePath ]metodo per salvare un'immagine nella directory Documenti e voglio caricarla ogni volta che l'app viene avviata. Ma ho un'immagine predefinita se non ci sono immagini salvate.

Ma non riesco a capire come usare la [ func fileExistsAtPath(_:) ]funzione. Qualcuno potrebbe fare un esempio dell'uso della funzione con un argomento path passato in essa.

Credo di non aver bisogno di incollare alcun codice in quanto questa è una domanda generica. Qualsiasi aiuto sarà molto apprezzato.

Saluti

Risposte:


248

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

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

Versione Swift 2.x , è necessario utilizzare 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")
    }

Sembra che la risposta sia stata aggiornata, quindi i commenti di absoluteString sembrano obsoleti.
Efren,

presumibilmente quei commenti erano che absoluteString non funziona da un URL, ma il percorso fa, che è quello che ho trovato!
CMash,

33

Controlla il codice qui sotto:

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

3
@SaqibOmer prova a trasmettere percorsi come NSString anziché String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
sheepgobeep

@PREMKUMAR Perché quella strana interpolazione di stringhe? È possibile utilizzare absoluteStringper convertire NSURLin pathma sarebbe meglio mantenere il percorso come una stringa ( NSString) come si fa in Swift 1.2.
Sulthan,

Ho trovato questa risposta per funzionare correttamente con Swift 2: stackoverflow.com/a/36897617/1245231
petrsyn

27

Oggi (2016) Apple consiglia sempre di più di utilizzare l'API relativa all'URL di NSURL, NSFileManagerecc.

Per ottenere la directory dei documenti in iOS e Swift 2 utilizzare

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

In try!questo caso è sicuro perché è garantita l'esistenza di questa directory standard.

Quindi aggiungere il componente del percorso appropriato, ad esempio un sqlitefile

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

Ora controlla se il file esiste con checkResourceIsReachableAndReturnErrorof NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

Se è necessario l'errore, passare il NSErrorpuntatore al parametro.

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è contrassegnato come può lanciare

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

Per considerare solo il valore di ritorno booleano e ignorare l'errore, utilizzare l'operatore a coalescenza nulla

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

Penso che in Swift 3 questo sia ora checkResourceIsReachable()e ritorni semplicemente Boolper URLtipo.
Ethan Allen,

1
Il problema che ho riscontrato è che sembra che tu non ottenga mai un valore "falso" da checkResourceIsReachable () in Swift3, solo un'eccezione se il file non è presente. Non sono molto contento di usare un'API in cui molte chiamate comporteranno un'eccezione anziché un semplice valore di ritorno.
Kendall Helmstetter Gelner,

Il try - catchpattern di @KendallHelmstetterGelner Swift non genera eccezioni. Non è confrontabile con le eccezioni in Objective-C. È un efficiente sistema di gestione degli errori.
Vadian

1
È più efficiente, lo so, ma concettualmente non mi piace. Non mi dispiace qualcosa per cui viene generata un'eccezione, un'eccezione. Ma un file inesistente NON è un'eccezione. È un caso comune e dovrebbe comportare un valore di ritorno falso, non una sorta di aberrazione con un oggetto Error avvolto che doveva essere creato. Potrebbe non sembrare molto, ma se hai decine di migliaia di file per verificare che il carico sia troppo elevato.
Kendall Helmstetter Gelner,

16

È abbastanza facile da usare. Basta lavorare con il singleton defaultManager di NSFileManager e quindi utilizzare il fileExistsAtPath()metodo, che accetta semplicemente una stringa come argomento e restituisce un valore bool, consentendogli di essere inserito direttamente nell'istruzione 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!!
}

Nota che il downcast su String non è necessario in Swift 2.


♦ per favore aiutatemi qui stackoverflow.com/questions/31503283/… . Non so quale codice debba scrivere.
Alexander Khitev,

6

Un modello di codice alternativo / raccomandato in Swift 3 sarebbe:

  1. Utilizzare l'URL invece di FileManager
  2. Uso della gestione delle eccezioni

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

5

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

Utilizzando: -

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

4

A beneficio dei principianti di Swift 3 :

  1. Swift 3 ha eliminato la maggior parte della sintassi NextStep
  2. Quindi NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain non vengono più utilizzati
  3. Utilizzare invece URL e FileManager
  4. NSSearchPathForDirectoriesInDomain non è necessario
  5. Utilizzare invece FileManager.default.urls

Ecco un esempio di codice per verificare se esiste un file denominato "database.sqlite" nella directory del documento dell'applicazione:

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

}

3

Molto semplice: se il tuo percorso è un'istanza URL, converti in stringa con il metodo '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
        }
    }

1

Questo funziona bene per 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

        }


}

Puoi verificare con questa chiamata:

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

            // your code if file exists

           } else {

           // your code if file does not exist

           }

Spero sia utile per qualcuno. @; -]


Cosa succede se l'utente non desidera solo controllare solo la directory del documento? e vuoi cercare un percorso generico
Jogendra Kumar

0

È necessario aggiungere una barra "/" prima del nome file oppure si ottiene un percorso come "... / DocumentsFilename.jpg"


0

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

Ho messo il segno di spunta nella mia funzione loadData che ho chiamato in viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

Quindi ho definito loadData di seguito.

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

0

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

dove "userInfo"- nome del file e "sqlite3"- estensione del file

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.