Comment vérifier si un fichier existe dans le répertoire Documents de Swift?

128

Comment vérifier si un fichier existe dans le répertoire Documents de Swift?

J'utilise une [ .writeFilePath ]méthode pour enregistrer une image dans le répertoire Documents et je souhaite la charger à chaque fois que l'application est lancée. Mais j'ai une image par défaut s'il n'y a pas d'image enregistrée.

Mais je ne peux tout simplement pas comprendre comment utiliser la [ func fileExistsAtPath(_:) ]fonction. Quelqu'un pourrait-il donner un exemple d'utilisation de la fonction avec un argument de chemin passé.

Je pense que je n'ai pas besoin de coller de code car c'est une question générique. Toute aide sera très appréciée.

À votre santé

GgnDpSingh
la source

Réponses:

249

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

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

Version Swift 2.x , besoin d'utiliser 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")
    }
mike.tihonchik
la source
Il semble que la réponse a été mise à jour, donc les commentaires de la chaîne absolue semblent obsolètes.
Efren
vraisemblablement, ces commentaires étaient qu'absoluString ne fonctionne pas à partir d'une URL, mais le chemin le fait, ce que j'ai trouvé!
CMash du
33

Vérifiez le code ci-dessous:

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");
}
PREMKUMAR
la source
3
@SaqibOmer essayez de convertir les chemins en NSString plutôt qu'en String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
Sheepgobeep
@PREMKUMAR Pourquoi cette étrange interpolation de chaîne? Vous pouvez utiliser absoluteStringpour convertir NSURLen pathmais il serait préférable de conserver le chemin sous forme de chaîne ( NSString) comme vous le faites dans Swift 1.2.
Sulthan
J'ai trouvé que cette réponse fonctionne correctement avec Swift 2: stackoverflow.com/a/36897617/1245231
petrsyn
27

De nos jours (2016), Apple recommande de plus en plus d'utiliser l'API liée aux URL de NSURL, NSFileManageretc.

Pour obtenir le répertoire des documents dans iOS et Swift 2, utilisez

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

Le try!est sûr dans ce cas car ce répertoire standard est garanti d'exister.

Ajoutez ensuite le composant de chemin approprié, par exemple un sqlitefichier

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

Vérifiez maintenant si le fichier existe avec checkResourceIsReachableAndReturnErrorof NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

Si vous avez besoin de l'erreur, passez le NSErrorpointeur sur le paramètre.

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

checkResourceIsReachableest marqué comme peut jeter

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

Pour ne considérer que la valeur de retour booléenne et ignorer l'erreur, utilisez l'opérateur nil-coalescing

let fileExists = (try? databaseURL.checkResourceIsReachable()) ?? false
vadian
la source
Je pense que dans Swift 3 c'est maintenant checkResourceIsReachable()et revient juste Boolpour le URLtype.
Ethan Allen
1
Le problème que j'ai trouvé est que vous ne semblez jamais obtenir une valeur "fausse" de checkResourceIsReachable () dans Swift3, juste une exception si le fichier n'est pas là. Je ne suis pas très content d'utiliser une API où de nombreux appels entraîneront une exception au lieu d'une simple valeur de retour.
Kendall Helmstetter Gelner
Le try - catchmodèle de @KendallHelmstetterGelner Swift ne lève pas d'exceptions. Ce n'est pas comparable aux exceptions d'Objective-C. C'est un système efficace de gestion des erreurs.
vadian le
1
C'est plus efficace je sais, mais conceptuellement je ne l'aime pas. Cela ne me dérange pas de lancer une exception pour - une exception. Mais un fichier qui n'existe pas n'est PAS une exception. C'est un cas courant et devrait entraîner une valeur de retour fausse, pas une sorte d'aberration avec un objet Error encapsulé qui a dû être créé. Cela peut sembler peu mais si vous avez des dizaines de milliers de fichiers à vérifier, le fardeau est trop élevé.
Kendall Helmstetter Gelner
16

C'est assez convivial. Il suffit de travailler avec le singleton defaultManager de NSFileManager, puis d'utiliser la fileExistsAtPath()méthode, qui prend simplement une chaîne comme argument, et renvoie un Bool, lui permettant d'être placé directement dans l'instruction 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!!
}

Notez que le downcast en String n'est pas nécessaire dans Swift 2.

Mick MacCallum
la source
♦ aidez-moi ici stackoverflow.com/questions/31503283/… . Je ne sais pas quel code doit écrire.
Alexander Khitev
6

Un modèle de code alternatif / recommandé dans Swift 3 serait:

  1. Utiliser l'URL au lieu de FileManager
  2. Utilisation de la gestion des exceptions

    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)")
        }
    }
Surya Kameswara Rao Ravi
la source
5

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

En utilisant: -

if fileUrl.checkFileExist()
   {
      // Do Something
   }
Lakhdeep Singh
la source
4

Au profit des débutants de Swift 3 :

  1. Swift 3 a supprimé la plupart de la syntaxe NextStep
  2. Donc NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain ne sont plus utilisés
  3. Utilisez plutôt URL et FileManager
  4. NSSearchPathForDirectoriesInDomain n'est pas nécessaire
  5. Utilisez plutôt FileManager.default.urls

Voici un exemple de code pour vérifier si un fichier nommé "database.sqlite" existe dans le répertoire des documents d'application:

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

}
Surya Kameswara Rao Ravi
la source
3

Très simple: si votre chemin est une instance d'URL, convertissez-le en chaîne par la méthode «chemin».

    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
        }
    }
Rohit Sisodia
la source
1

Cela fonctionne bien pour moi dans 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

        }


}

Vous pouvez vérifier avec cet appel:

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

            // your code if file exists

           } else {

           // your code if file does not exist

           }

J'espère que c'est utile pour quelqu'un. @; -]

Maurizio FIORINO
la source
Que faire si l'utilisateur ne souhaite pas uniquement vérifier le répertoire des documents? et que vous voulez rechercher un chemin générique
Jogendra Kumar
0

Vous devez ajouter une barre oblique "/" avant le nom du fichier, ou vous obtenez un chemin comme "... / DocumentsFilename.jpg"

Jauzee
la source
0

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

J'ai mis le chèque dans ma fonction loadData que j'ai appelée dans viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

Ensuite, j'ai défini loadData ci-dessous.

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...")
    }
}
Danse Joshua
la source
0

travaille chez 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"- le nom du fichier, et "sqlite3"- l'extension du fichier

Nastassia
la source