Як перевірити, чи існує файл у каталозі Документи у Свіфті?


127

Як перевірити, чи існує файл у каталозі Документи у Swift?

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

Але я просто не можу голову, як використовувати цю [ func fileExistsAtPath(_:) ]функцію. Чи може хтось навести приклад використання функції з переданим в неї аргументом шляху.

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

Ура

Відповіді:


248

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

Схоже, що відповідь було оновлено, тому коментарі Absolring String здаються застарілими.
Ефрен

Мабуть, ці коментарі полягали в тому, що absolString працює не з URL-адреси, але шлях працює, і це те, що я знайшов!
CMash

33

Перевірте наведений нижче код:

Швидкий 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");
}

Швидкий 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 пробуйте кастинг шляхів як NSString, а не String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
вівчарка

@PREMKUMAR Чому дивна інтерполяція рядків? Ви могли б використовувати , absoluteStringщоб перетворити NSURLв , pathале було б краще просто тримати шлях у вигляді рядка ( NSString) , як ви робите в Swift 1.2.
Султан

Я знайшов відповідь на роботу правильно з Swift 2: stackoverflow.com/a/36897617/1245231
petrsyn

27

В даний час (2016) Apple рекомендує все більше і більше , щоб використовувати URL пов'язаний API з 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) }

Швидкий 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

Я думаю, що в Swift 3 це зараз checkResourceIsReachable()і просто повертається Boolдля URLтипу.
Етан Аллен

1
Проблема, яку я знайшов, полягає в тому, що ви ніколи не отримуєте значення "false" від checkResourceIsReachable () у Swift3, лише виняток, якщо файлу немає. Я не дуже радий користуватися API, де багато дзвінків призведе до виключення замість простого повернення.
Kendall Helmstetter Gelner

Шаблон @KendallHelmstetterGelner Swift try - catchне викидає винятків. Це не можна порівняти з винятками в Objective-C. Це ефективна система обробки помилок.
вадіан

1
Я знаю, що це більш ефективно, але концептуально це мені не подобається. Я не заперечую, щоб кинути виняток для - винятку. Але файл, який не існує, НЕ є винятком. Це звичайний випадок і має спричинити помилкове значення повернення, а не якесь відхилення від загорнутого об’єкта Error, який потрібно було створити. Це може здатися не так вже й багато, але якщо у вас є десятки тисяч файлів, щоб перевірити навантаження занадто висока.
Kendall Helmstetter Gelner

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

Швидкий 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"


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"файлу та - розширення файлу

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.