¿Cómo verificar si existe un archivo en el directorio Documentos en Swift?

127

¿Cómo verificar si existe un archivo en el directorio Documentos en Swift?

Estoy usando un [ .writeFilePath ]método para guardar una imagen en el directorio Documentos y quiero cargarla cada vez que se inicia la aplicación. Pero tengo una imagen predeterminada si no hay una imagen guardada.

Pero no puedo entender cómo usar la [ func fileExistsAtPath(_:) ]función. ¿Podría alguien dar un ejemplo de uso de la función con un argumento de ruta pasado a ella?

Creo que no necesito pegar ningún código allí, ya que esta es una pregunta genérica. Cualquier ayuda será muy apreciada.

Salud

GgnDpSingh
fuente

Respuestas:

248

Versión 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")
    }

Versión 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")
    }

Versión Swift 2.x , necesita usar 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
fuente
Parece que la respuesta se actualizó, por lo que los comentarios de absoluteString parecen obsoletos.
Efren
presumiblemente esos comentarios fueron que absoluteString no funciona desde una URL, pero la ruta sí, que es lo que encontré.
CMash
33

Verifique el siguiente código:

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
fuente
3
@SaqibOmer intenta lanzar rutas como NSString en lugar de String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
sheepgobeep
@PREMKUMAR ¿Por qué esa extraña interpolación de cuerdas? Se podría utilizar absoluteStringpara convertir NSURLa path, pero sería mejor que sólo seguir el camino como una cadena ( NSString) como se hace en Swift 1.2.
Sulthan
Encontré que esta respuesta funciona correctamente con Swift 2: stackoverflow.com/a/36897617/1245231
petrsyn
27

Hoy en día (2016) Apple recomienda cada vez más usar la API relacionada con URL de NSURL, NSFileManageretc.

Para obtener el directorio de documentos en iOS y Swift 2 use

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

El try!es seguro en este caso porque se garantiza que este directorio estándar existe.

Luego agregue el componente de ruta apropiado, por ejemplo, un sqlitearchivo

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

Ahora compruebe si el archivo existe con checkResourceIsReachableAndReturnErrorde NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

Si necesita el error, pase el NSErrorpuntero al parámetro.

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á marcado como puede lanzar

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

Para considerar solo el valor de retorno booleano e ignorar el error, utilice el operador de fusión nula

let fileExists = (try? databaseURL.checkResourceIsReachable()) ?? false
vadian
fuente
Creo que en Swift 3 esto es ahora checkResourceIsReachable()y solo regresa Boolpor URLtipo.
Ethan Allen
1
El problema que encontré es que nunca parece obtener un valor "falso" de checkResourceIsReachable () en Swift3, solo una excepción si el archivo no está allí. No estoy muy contento de usar una API donde muchas llamadas resultarán en una excepción en lugar de un simple valor de retorno.
Kendall Helmstetter Gelner
El try - catchpatrón de @KendallHelmstetterGelner Swift no arroja excepciones. No es comparable con excepciones en Objective-C. Es un sistema eficiente de manejo de errores.
vadian
1
Es más eficiente, lo sé, pero conceptualmente no me gusta. No me importa que algo arroje una excepción, una excepción. Pero un archivo que no existe NO es una excepción. Es un caso común y debería dar como resultado un valor de retorno falso, no un tipo de aberración con un objeto de error envuelto que tuvo que ser creado. Puede que no parezca mucho, pero si tiene decenas de miles de archivos para verificar, la carga es demasiado alta.
Kendall Helmstetter Gelner
16

Es bastante fácil de usar. Simplemente trabaje con el singleton predeterminado de NSFileManager y luego use el fileExistsAtPath()método, que simplemente toma una cadena como argumento y devuelve un Bool, lo que permite que se coloque directamente en la instrucción 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!!
}

Tenga en cuenta que el downcast a String no es necesario en Swift 2.

Mick MacCallum
fuente
♦ por favor ayúdame aquí stackoverflow.com/questions/31503283/… . No sé qué código necesito escribir.
Alexander Khitev
6

Un patrón de código alternativo / recomendado en Swift 3 sería:

  1. Usar URL en lugar de FileManager
  2. Uso de manejo de excepciones

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

Utilizando: -

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

Para el beneficio de los principiantes de Swift 3 :

  1. Swift 3 ha eliminado la mayor parte de la sintaxis NextStep
  2. Entonces NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain ya no se usan
  3. En su lugar, use URL y FileManager
  4. NSSearchPathForDirectoriesInDomain no es necesario
  5. En su lugar, use FileManager.default.urls

Aquí hay una muestra de código para verificar si existe un archivo llamado "database.sqlite" en el directorio de documentos de la aplicación:

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
fuente
3

Muy simple: si su ruta es una instancia de URL, conviértala en cadena mediante el método 'ruta'.

    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
fuente
1

Esto funciona bien para mí en 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

        }


}

Puede verificar con esta llamada:

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

            // your code if file exists

           } else {

           // your code if file does not exist

           }

Espero que sea útil para alguien. @; -]

Maurizio FIORINO
fuente
¿Qué sucede si el usuario no desea verificar solo el directorio de documentos? y quiere buscar una ruta genérica
Jogendra Kumar
0

Debe agregar una barra inclinada "/" antes del nombre de archivo, u obtendrá una ruta como "... / DocumentsFilename.jpg"

Jauzee
fuente
0

Swift 4 ejemplo:

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

Puse el cheque en mi función loadData que invoqué en viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

Luego definí loadData a continuación.

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...")
    }
}
Joshua Dance
fuente
0

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

donde "userInfo"- nombre del archivo y "sqlite3"- extensión del archivo

nastassia
fuente