Jak sprawdzić, czy plik istnieje w folderze Dokumenty?

216

Mam aplikację z Zakupem w aplikacji, która gdy użytkownik coś kupuje, pobiera jeden plik HTML do folderu Dokumenty mojej aplikacji.

Teraz muszę sprawdzić, czy ten plik HTML istnieje, więc jeśli to prawda, załaduj ten plik HTML, w przeciwnym razie załaduj moją domyślną stronę HTML.

Jak mogę to zrobić? Dzięki NSFileManagernie mogę wyjść poza mainBundle...

Obliviux
źródło
„Dzięki NSFileManager nie mogę wyjść poza mainBundle” - skąd wziął się ten błąd?

Odpowiedzi:

521

Swift 3:

let documentsURL = try! FileManager().url(for: .documentDirectory,
                                          in: .userDomainMask,
                                          appropriateFor: nil,
                                          create: true)

... daje adres URL pliku katalogu dokumentów. Poniższe sprawdza, czy istnieje plik o nazwie foo.html:

let fooURL = documentsURL.appendingPathComponent("foo.html")
let fileExists = FileManager().fileExists(atPath: fooURL.path)

Cel C:

NSString* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

NSString* foofile = [documentsPath stringByAppendingPathComponent:@"foo.html"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
Nikolai Ruhe
źródło
12
Pamiętaj, że ładujesz plik z osobistego katalogu dokumentów aplikacji, a nie z globalnego, który znajdziesz, jeśli masz jailbreak. Jeśli zainstalujesz aplikację w / Applications tak, jakby była to główna aplikacja, będziesz mieć dostęp do całego systemu plików i będziesz korzystać z udostępnionego katalogu Dokumenty. Jeśli zainstalujesz go za pomocą iTunes lub XCode, będziesz korzystać z osobistego katalogu swoich aplikacji. Miło jest przechowywać pliki w katalogu lokalnym w celu tworzenia kopii zapasowych.
Epsilon Prime
6
objectAtIndex: 0 można teraz zastąpić firstObject
Govind
3
Lub po prostu [0]poprzez dostęp do indeksu
tymczasowego
firstObject jest bezpieczniejszy niż [0] i objectAtIndex: 0
Itachi
1
@Itachi Właściwie w tym przypadku wolę wyjątek, gdy nie ma obiektu w tablicy. Jeśli wynikiem firstObjectjest, nilnie ma rozsądnego sposobu, w jaki program mógłby kontynuować, ponieważ coś w ramach Apple jest poważnie zepsute.
Nikolai Ruhe
14

Apple odradza poleganie na metodzie fileExistAtPath:. Często lepiej jest po prostu spróbować otworzyć plik i poradzić sobie z błędem, jeśli plik nie istnieje.

Odwołanie do klasy NSFileManager

Uwaga: Próba predykcji zachowania na podstawie bieżącego stanu systemu plików lub określonego pliku w systemie plików nie jest zalecana. Może to spowodować dziwne zachowanie lub wyścig. Zdecydowanie lepiej jest spróbować wykonać operację (na przykład załadować plik lub utworzyć katalog), sprawdzić błędy i obsłużyć je z wdziękiem, niż próbować z wyprzedzeniem ustalić, czy operacja się powiedzie. Aby uzyskać więcej informacji na temat warunków wyścigu w systemie plików, zobacz „Warunki wyścigu i bezpieczne operacje na plikach” w Przewodniku bezpiecznego kodowania.

Źródło: Apple API API Reference

Z bezpiecznego przewodnika kodowania.

Aby temu zapobiec, programy często sprawdzają, czy plik tymczasowy o określonej nazwie już nie istnieje w katalogu docelowym. Jeśli taki plik istnieje, aplikacja usuwa go lub wybiera nową nazwę pliku tymczasowego, aby uniknąć konfliktu. Jeśli plik nie istnieje, aplikacja otwiera plik do zapisu, ponieważ procedura systemowa, która otwiera plik do zapisu, automatycznie tworzy nowy plik, jeśli nie istnieje. Osoba atakująca, stale uruchamiając program, który tworzy nowy plik tymczasowy o odpowiedniej nazwie, może (przy odrobinie wytrwałości i przy odrobinie szczęścia) utworzyć plik w przerwie między sprawdzaniem przez aplikację, aby upewnić się, że plik tymczasowy nie istnieje a kiedy otwiera to do pisania. Następnie aplikacja otwiera plik atakującego i zapisuje go (pamiętaj, że procedura systemowa otwiera istniejący plik, jeśli taki istnieje, i tworzy nowy plik tylko wtedy, gdy nie istnieje żaden plik). Plik osoby atakującej może mieć inne uprawnienia dostępu niż plik tymczasowy aplikacji, dzięki czemu osoba atakująca może następnie odczytać zawartość. Alternatywnie, osoba atakująca może mieć plik już otwarty. Osoba atakująca może zastąpić plik linkiem twardym lub dowiązaniem symbolicznym do innego pliku (należącego do niego lub istniejącego pliku systemowego). Na przykład osoba atakująca może zastąpić ten plik dowiązaniem symbolicznym do pliku haseł systemowych, aby po ataku hasła systemowe zostały uszkodzone do tego stopnia, że ​​nikt, w tym administrator systemu, nie może się zalogować. Alternatywnie, osoba atakująca może mieć plik już otwarty. Osoba atakująca może zastąpić plik linkiem twardym lub dowiązaniem symbolicznym do innego pliku (należącego do niego lub istniejącego pliku systemowego). Na przykład osoba atakująca może zastąpić ten plik dowiązaniem symbolicznym do pliku haseł systemowych, aby po ataku hasła systemowe zostały uszkodzone do tego stopnia, że ​​nikt, w tym administrator systemu, nie może się zalogować. Alternatywnie, osoba atakująca może mieć plik już otwarty. Osoba atakująca może zastąpić plik linkiem twardym lub dowiązaniem symbolicznym do innego pliku (należącego do niego lub istniejącego pliku systemowego). Na przykład osoba atakująca może zastąpić ten plik dowiązaniem symbolicznym do pliku haseł systemowych, aby po ataku hasła systemowe zostały uszkodzone do tego stopnia, że ​​nikt, w tym administrator systemu, nie może się zalogować.

orkoden
źródło
1
Chociaż sama w sobie jest dobrą odpowiedzią, stanowi świetną poradę. Dobrze byłoby zobaczyć, jak można to zaimplementować za pomocą małego przykładu kodu.
SnareChops
8

Jeśli konfigurujesz system plików inaczej lub szukasz innego sposobu konfiguracji systemu plików, a następnie sprawdzasz, czy plik istnieje w folderze dokumentów, oto kolejny przykład. Pokaż także sprawdzanie dynamiczne

for (int i = 0; i < numberHere; ++i){
    NSFileManager* fileMgr = [NSFileManager defaultManager];
    NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    NSString* imageName = [NSString stringWithFormat:@"image-%@.png", i];
    NSString* currentFile = [documentsDirectory stringByAppendingPathComponent:imageName];
    BOOL fileExists = [fileMgr fileExistsAtPath:currentFile];
    if (fileExists == NO){
        cout << "DOESNT Exist!" << endl;
    } else {
        cout << "DOES Exist!" << endl;
    }
}
John Riselvato
źródło
4

Swift 2.0

Oto jak sprawdzić, czy plik istnieje za pomocą Swift

func isFileExistsInDirectory() -> Bool {
    let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let documentsDirectory: AnyObject = paths[0]
    let dataPath = documentsDirectory.stringByAppendingPathComponent("/YourFileName")

    return NSFileManager.defaultManager().fileExistsAtPath(dataPath)
}
Tal Zion
źródło
3

sprawdź, czy plik istnieje w ścieżce dokumentu / catchimage:

NSString *stringPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
NSString *tempName = [NSString stringWithFormat:@"%@/catchimage/%@.png",stringPath,@"file name"];
NSLog(@"%@",temName);
if([[NSFileManager defaultManager] fileExistsAtPath:temName]){
    // ur code here
} else {
    // ur code here** 
}
Mani
źródło
0
NSArray *directoryPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *imagePath =  [directoryPath objectAtIndex:0];
//If you have superate folder
imagePath= [imagePath stringByAppendingPathComponent:@"ImagesFolder"];//Get docs dir path with folder name
_imageName = [_imageName stringByAppendingString:@".jpg"];//Assign image name
imagePath= [imagePath stringByAppendingPathComponent:_imageName];
NSLog(@"%@", imagePath);

//Method 1:
BOOL file = [[NSFileManager defaultManager] fileExistsAtPath: imagePath];
if (file == NO){
    NSLog("File not exist");
} else {
    NSLog("File exist");
}

//Method 2:
NSData *data = [NSData dataWithContentsOfFile:imagePath];
UIImage *image = [UIImage imageWithData:data];
if (!(image == nil)) {//Check image exist or not
    cell.photoImageView.image = image;//Display image
}
iOS
źródło
0

NSURL.h pod warunkiem, - (BOOL)checkResourceIsReachableAndReturnError:(NSError **)erroraby to zrobić

NSURL *fileURL = [NSURL fileURLWithPath:NSHomeDirectory()];
NSError * __autoreleasing error = nil;
if ([fileURL checkResourceIsReachableAndReturnError:&error]) {
    NSLog(@"%@ exists", fileURL);
} else {
    NSLog(@"%@ existence checking error: %@", fileURL, error);
}

Lub używając Swift

if let url = URL(fileURLWithPath: NSHomeDirectory()) {
    do {
        let result = try url.checkResourceIsReachable()
    } catch {
        print(error)
    }
}
DawnSong
źródło