Как проверить, существует ли файл в каталоге документов в Swift?

128

Как проверить, существует ли файл в каталоге документов в Swift?

Я использую [ .writeFilePath ]метод для сохранения изображения в каталоге документов и хочу загружать его каждый раз при запуске приложения. Но у меня есть изображение по умолчанию, если нет сохраненного изображения.

Но я просто не могу понять, как использовать эту [ func fileExistsAtPath(_:) ]функцию. Может ли кто-нибудь привести пример использования функции с переданным в нее аргументом пути.

Я считаю, что мне не нужно вставлять туда какой-либо код, поскольку это общий вопрос. Любая помощь будет высоко ценится.

ура

GgnDpSingh
источник

Ответы:

249

Версия 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")
    }

Версия 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")
    }

Версия Swift 2.x , необходимо использовать 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
источник
Похоже, ответ был обновлен, поэтому комментарии absoluteString кажутся устаревшими.
Эфрен
предположительно, эти комментарии заключались в том, что absoluteString не работает с URL-адресом, а path работает, что я обнаружил!
CMash
33

Проверьте приведенный ниже код:

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
источник
3
@SaqibOmer попробуйте преобразовать пути как NSString, а не как String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
Sheepgobeep
@PREMKUMAR Почему такая странная интерполяция строк? Вы можете использовать absoluteStringдля преобразования NSURLв, pathно было бы лучше просто сохранить путь в виде строки ( NSString), как в Swift 1.2.
Sulthan
Я нашел, что этот ответ правильно работает со Swift 2: stackoverflow.com/a/36897617/1245231
petrsyn
27

В настоящее время (2016 г.) Apple все больше и больше рекомендует использовать API, связанные с URL NSURL, NSFileManagerи т. Д.

Чтобы получить каталог документов в iOS и Swift 2, используйте

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

В try!этом случае это безопасно, потому что этот стандартный каталог гарантированно существует.

Затем добавьте соответствующий компонент пути, например sqliteфайл

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

Теперь проверьте, существует ли файл с checkResourceIsReachableAndReturnErrorоф NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

Если вам нужна ошибка, передайте NSErrorуказатель на параметр.

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помечено как можно бросить

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

Чтобы учитывать только логическое возвращаемое значение и игнорировать ошибку, используйте оператор nil-coalescing

let fileExists = (try? databaseURL.checkResourceIsReachable()) ?? false
vadian
источник
Я думаю, что в Swift 3 это сейчас checkResourceIsReachable()и просто возвращается Boolдля URLтипа.
Итан Аллен
1
Проблема, которую я обнаружил, заключается в том, что вы никогда не получаете «ложного» значения от checkResourceIsReachable () в Swift3, это просто исключение, если файла нет. Я не очень доволен использованием API, в котором множество вызовов приведет к исключению вместо простого возвращаемого значения.
Кендалл Хельмштеттер Гельнер
Шаблон @KendallHelmstetterGelner Swift try - catchне создает исключений. Это не сравнимо с исключениями в Objective-C. Это эффективная система обработки ошибок.
vadian 04
1
Я знаю, это более эффективно, но концептуально мне это не нравится. Я не против того, чтобы что-то бросило исключение - исключение. Но несуществующий файл НЕ является исключением. Это распространенный случай, и он должен приводить к ложному возвращаемому значению, а не к какой-то аберрации с обернутым объектом Error, который необходимо было создать. Может показаться, что это не так уж и много, но если у вас есть десятки тысяч файлов для проверки, нагрузка слишком высока.
Кендалл Хельмштеттер Гельнер,
16

Это довольно удобно. Просто работайте с синглтоном NSFileManager defaultManager, а затем используйте fileExistsAtPath()метод, который просто принимает строку в качестве аргумента и возвращает Bool, позволяя разместить его непосредственно в операторе 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!!
}

Обратите внимание, что преобразование в String не требуется в Swift 2.

Мик МакКаллум
источник
♦ пожалуйста, помогите мне здесь stackoverflow.com/questions/31503283/… . Я не знаю, какой код нужно писать.
Александр Хитев
6

Альтернативный / рекомендуемый шаблон кода в Swift 3 :

  1. Используйте URL вместо FileManager
  2. Использование обработки исключений

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

С помощью: -

if fileUrl.checkFileExist()
   {
      // Do Something
   }
Лахдип Сингх
источник
4

Для новичков в Swift 3 :

  1. Swift 3 покончил с большей частью синтаксиса NextStep
  2. Таким образом, NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain больше не используются
  3. Вместо этого используйте URL и FileManager
  4. NSSearchPathForDirectoriesInDomain не требуется
  5. Вместо этого используйте FileManager.default.urls

Вот пример кода, чтобы проверить, существует ли файл с именем «database.sqlite» в каталоге документов приложения:

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

Очень просто: если ваш путь является экземпляром URL-адреса, преобразовать его в строку методом '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

Это отлично работает для меня в 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

        }


}

Вы можете проверить с помощью этого звонка:

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

            // your code if file exists

           } else {

           // your code if file does not exist

           }

Надеюсь, это кому-то пригодится. @; -]

Маурицио ФИОРИНО
источник
Что, если пользователь не хочет проверять только каталог документов? и хотите найти общий путь
Джогендра Кумар
0

Вы должны добавить косую черту "/" перед именем файла, иначе вы получите путь как "... / DocumentsFilename.jpg"

Jauzee
источник
0

Пример 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)
}

Я поставил проверку в свою функцию loadData, которую я вызвал в viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

Затем я определил loadData ниже.

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

работает на 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"- имя файла, а "sqlite3"- расширение файла

Настасья
источник