Jak sprawdzić, czy plik istnieje w katalogu Dokumenty w Swift?


127

Jak sprawdzić, czy plik istnieje w katalogu Dokumenty w Swift?

Używam [ .writeFilePath ]metody zapisywania obrazu w katalogu Dokumenty i chcę go ładować za każdym razem, gdy aplikacja jest uruchamiana. Ale mam domyślny obraz, jeśli nie ma zapisanego obrazu.

Ale po prostu nie mogę się dowiedzieć, jak używać tej [ func fileExistsAtPath(_:) ]funkcji. Czy ktoś mógłby podać przykład użycia funkcji z przekazanym argumentem path.

Uważam, że nie muszę wklejać tam żadnego kodu, ponieważ jest to ogólne pytanie. Każda pomoc będzie mile widziana.

Twoje zdrowie

Odpowiedzi:


248

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

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

Wersja Swift 2.x , musisz użyć 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")
    }

Wygląda na to, że odpowiedź została zaktualizowana, więc komentarze AbsolutString wydają się przestarzałe.
— Efren

przypuszczalnie te komentarze były takie, że bezwzględny ciąg nie działa z adresu URL, ale ścieżka działa, co znalazłem!
— CMash

33

Sprawdź poniższy kod:

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 spróbuj rzutować ścieżki jako NSString zamiast String. var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
— sheepgobeep

@PREMKUMAR Dlaczego ta dziwna interpolacja ciągów? Możesz użyć absoluteStringdo konwersji NSURLna, pathale lepiej byłoby zachować ścieżkę jako string ( NSString), tak jak w Swift 1.2.
— Sulthan

Uważam, że ta odpowiedź działa poprawnie ze Swift 2: stackoverflow.com/a/36897617/1245231
— petrsyn

27

Obecnie (2016) Apple zaleca bardziej używać URL powiązany API NSURL, NSFileManageritd.

Aby uzyskać katalog dokumentów w iOS i Swift 2 użyj

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

W try!tym przypadku jest bezpieczny, ponieważ istnieje gwarancja, że ​​ten standardowy katalog istnieje.

Następnie dołącz odpowiedni składnik ścieżki, na przykład plik sqlite plik

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

Teraz sprawdź, czy plik istnieje z checkResourceIsReachableAndReturnErroro NSURL.

let fileExists = databaseURL.checkResourceIsReachableAndReturnError(nil)

Jeśli potrzebujesz błędu, przekaż NSErrorwskaźnik do parametru.

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

checkResourceIsReachablejest oznaczony jako może rzucać

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

Aby wziąć pod uwagę tylko wartość logiczną zwracaną i zignorować błąd, użyj operatora łączenia zerowego

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

Myślę, że w Swift 3 jest to teraz checkResourceIsReachable()i po prostu wraca Booldo URLtypu.
— Ethan Allen,

1
Problem, który znalazłem, polega na tym, że nigdy nie wydaje się, że otrzymujesz wartość „false” z checkResourceIsReachable () w Swift3, tylko wyjątek, jeśli nie ma pliku. Nie jestem zbyt zadowolony z korzystania z interfejsu API, w którym wiele wywołań spowoduje wyjątek zamiast prostej wartości zwracanej.
— Kendall Helmstetter Gelner

Wzorzec @KendallHelmstetterGelner Swift try - catchnie zgłasza wyjątków. Nie da się tego porównać z wyjątkami w Objective-C. To wydajny system obsługi błędów.
— Vadian

1
Wiem, że jest wydajniejszy, ale koncepcyjnie mi się to nie podoba. Nie mam nic przeciwko rzucaniu wyjątków - wyjątków. Ale nieistniejący plik NIE jest wyjątkiem. Jest to typowy przypadek i powinien skutkować fałszywą wartością zwracaną, a nie jakimś rodzajem aberracji z opakowanym obiektem Error, który musiał zostać utworzony. Może się wydawać, że to niewiele, ale jeśli masz dziesiątki tysięcy plików, to obciążenie jest zbyt duże.
— Kendall Helmstetter Gelner

16

Jest całkiem przyjazny dla użytkownika. Po prostu pracuj z singletonem defaultManager NSFileManager, a następnie użyj fileExistsAtPath()metody, która po prostu przyjmuje ciąg znaków jako argument i zwraca wartość Bool, umożliwiając umieszczenie go bezpośrednio w instrukcji 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!!
}

Zauważ, że obniżenie do String nie jest konieczne w Swift 2.


♦ pomóż mi tutaj stackoverflow.com/questions/31503283/… . Nie wiem, który kod muszę napisać.
— Alexander Khitev

6

Alternatywny / zalecany wzorzec kodu w Swift 3 to:

  1. Użyj adresu URL zamiast FileManager
  2. Korzystanie z obsługi wyjątków

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

Za pomocą: -

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

4

Z korzyścią dla początkujących użytkowników Swift 3 :

  1. Swift 3 wyeliminował większość składni NextStep
  2. Dlatego NSURL, NSFilemanager, NSSearchPathForDirectoriesInDomain nie są już używane
  3. Zamiast tego użyj adresu URL i menedżera plików
  4. NSSearchPathForDirectoriesInDomain nie jest potrzebne
  5. Zamiast tego użyj FileManager.default.urls

Oto przykładowy kod do sprawdzenia, czy plik o nazwie „database.sqlite” istnieje w katalogu dokumentów aplikacji:

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

Bardzo proste: jeśli ścieżka jest instancją adresu URL, przekonwertuj ją na ciąg przy użyciu metody „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

Działa to dobrze dla mnie w 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

        }


}

Możesz sprawdzić za pomocą tego połączenia:

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

            // your code if file exists

           } else {

           // your code if file does not exist

           }

Mam nadzieję, że komuś się przyda. @; -]


A co, jeśli użytkownik nie chce po prostu sprawdzić tylko katalogu dokumentów? i chcesz poszukać ogólnej ścieżki
— Jogendra Kumar

0

Musisz dodać ukośnik „/” przed nazwą pliku lub uzyskać ścieżkę, taką jak „... / DocumentsFilename.jpg”


0

Przykład języka 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)
}

Umieściłem kontrolę w mojej funkcji loadData, którą wywołałem w viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
}

Następnie zdefiniowałem loadData poniżej.

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

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

gdzie "userInfo"- nazwa "sqlite3"pliku i - rozszerzenie pliku

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.