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

GgnDpSingh
fonte

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")
    }
mike.tihonchik
fonte
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");
}
PREMKUMAR
fonte
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
vadian
fonte
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.

Mick MacCallum
fonte
♦ 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)")
        }
    }
Surya Kameswara Rao Ravi
fonte
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
   }
Lakhdeep Singh
fonte
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)")
    }

}
Surya Kameswara Rao Ravi
fonte
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
        }
    }
Rohit Sisodia
fonte
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. @; -]

Maurizio FIORINO
fonte
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"

Jauzee
fonte
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...")
    }
}
Joshua Dance
fonte
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

nastassia
fonte