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

GgnDpSingh
źródło

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")
    }
mike.tihonchik
źródło
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");
}
PREMKUMAR
źródło
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
vadian
źródło
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.

Mick MacCallum
źródło
♦ 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)")
        }
    }
Surya Kameswara Rao Ravi
źródło
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
   }
Lakhdeep Singh
źródło
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)")
    }

}
Surya Kameswara Rao Ravi
źródło
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
        }
    }
Rohit Sisodia
źródło
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. @; -]

Maurizio FIORINO
źródło
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”

Jauzee
źródło
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...")
    }
}
Joshua Dance
źródło
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

nastassia
źródło