Como verificar se existe um arquivo no diretório Documents no Swift?


127

Como verificar se existe um arquivo no diretório Documents Swift?

Estou usando o [ .writeFilePath ]método para salvar uma imagem no diretório Documents e quero carregá-la sempre que o aplicativo for iniciado. Mas eu tenho uma imagem padrão se não houver imagem salva.

Mas eu simplesmente não consigo entender como usar a [ func fileExistsAtPath(_:) ]função. Alguém poderia dar um exemplo de uso da função com um argumento de caminho passado para ela.

Acredito que não preciso colar nenhum código, pois essa é uma pergunta genérica. Qualquer ajuda será muito apreciada.

Felicidades

Respostas:


248

Versão 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")
    }

Versão 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")
    }

Na versão Swift 2.x , é necessário 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")
    }

Parece que a resposta foi atualizada, portanto os comentários absolutos em String parecem obsoletos.
Efren

presumivelmente, esses comentários foram que absoluteString não funciona a partir de uma URL, mas o caminho, o que eu achei!
CMash

33

Verifique o código abaixo:

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 tente converter caminhos como NSString em vez de String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
sheepgobeep

@PREMKUMAR Por que essa interpolação de string estranha? Você pode usar absoluteStringpara converter NSURLpara, pathmas seria melhor manter o caminho como uma string ( NSString) como no Swift 1.2.
Sulthan

Eu encontrei esta resposta para trabalho corretamente com Swift 2: stackoverflow.com/a/36897617/1245231
petrsyn

27

Hoje em dia (2016) Apple recomenda mais e mais para usar a API relacionada URL de NSURL, NSFileManageretc.

Para obter o diretório de documentos no iOS e no Swift 2, use

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

O try!é seguro neste caso, porque este diretório padrão é garantido que existe.

Em seguida, acrescente o componente de caminho apropriado, por exemplo, um sqlitearquivo

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

Agora verifique se o arquivo existe com checkResourceIsReachableAndReturnErrorof NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

Se você precisar do erro, passe o NSErrorponteiro para o 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 pode jogar

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

Para considerar apenas o valor de retorno booleano e ignorar o erro, use o operador nil-coalescing

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

Eu acho que no Swift 3 é agora checkResourceIsReachable()e apenas retorna Boolpara o URLtipo.
Ethan Allen

1
O problema que encontrei é que você nunca parece obter um valor "falso" de checkResourceIsReachable () no Swift3, apenas uma exceção se o arquivo não estiver lá. Não estou muito feliz ao usar uma API em que muitas chamadas resultarão em uma exceção, em vez de um simples valor de retorno.
Kendall Helmstetter Gelner

O try - catchpadrão do @KendallHelmstetterGelner Swift não gera exceções. Não é comparável com exceções no Objective-C. É um sistema eficiente de tratamento de erros.
vadian

1
É mais eficiente, eu sei, mas conceitualmente não gosto. Não me importo que algo lance uma exceção - uma exceção. Mas um arquivo não existente NÃO é uma exceção. É um caso comum e deve resultar em um valor de retorno falso, não em algum tipo de aberração com um objeto Error que precisou ser criado. Pode não parecer muito, mas se você tiver dezenas de milhares de arquivos para verificar se a carga é muito alta.
Kendall Helmstetter Gelner

16

É bastante fácil de usar. Apenas trabalhe com o singleton defaultManager do NSFileManager e use o fileExistsAtPath()método, que simplesmente pega uma string como argumento e retorna um Bool, permitindo que seja colocado diretamente na instrução 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!!
}

Observe que o downcast para String não é necessário no Swift 2.


♦ por favor me ajude aqui stackoverflow.com/questions/31503283/… . Não sei qual código precisa escrever.
Alexander Khitev 19/07

6

Um padrão de código alternativo / recomendado no Swift 3 seria:

  1. Use URL em vez de FileManager
  2. Uso de tratamento de exceção

    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

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

Usando: -

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

4

Para o benefício dos iniciantes do Swift 3 :

  1. Swift 3 acabou com a maioria da sintaxe NextStep
  2. Portanto, NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain não são mais usados
  3. Em vez disso, use URL e FileManager
  4. NSSearchPathForDirectoriesInDomain não é necessário
  5. Em vez disso, use FileManager.default.urls

Aqui está um exemplo de código para verificar se existe um arquivo chamado "database.sqlite" no diretório de documentos do aplicativo:

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

Muito simples: se o seu caminho for uma instância de URL, converta em string pelo método '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

Isso funciona bem para mim no 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

        }


}

Você pode verificar com esta ligação:

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

            // your code if file exists

           } else {

           // your code if file does not exist

           }

Espero que seja útil para alguém. @; -]


E se o usuário não quiser apenas verificar o diretório do documento? e deseja pesquisar um caminho genérico
Jogendra Kumar

0

Você deve adicionar uma barra "/" antes do nome do arquivo ou obter um caminho como "... / DocumentsFilename.jpg"


0

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

Coloquei a verificação na minha função loadData que chamei em viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

Então eu defini loadData abaixo.

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

trabalha na 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"- nome do arquivo e "sqlite3"- extensão do arquivo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.