Как проверить, существует ли файл в папке «Документы»?


216

У меня есть приложение с покупкой в ​​приложении, которое, когда пользователь что-то покупает, загружает один html-файл в папку «Мои документы» моего приложения.

Теперь я должен проверить, существует ли этот HTML-файл, поэтому, если true, загрузите этот HTML-файл, иначе загрузите мою HTML-страницу по умолчанию.

Как я могу это сделать? С NSFileManagerя не могу выйти на улицу mainBundle..


«С NSFileManager я не могу выбраться из mainBundle» - откуда вы взяли этот кусочек дезинформации?

Ответы:


521

Свифт 3:

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

... дает вам URL файла каталога документов. Далее проверяется, есть ли файл с именем foo.html:

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

Objective-C:

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

NSString* foofile = [documentsPath stringByAppendingPathComponent:@"foo.html"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];

12
Обратите внимание, что вы загружаете файл из личного каталога документов вашего приложения, а не из глобального, который вы найдете, если вы взломаны. Если вы установите приложение в / Applications, как если бы оно было основным, у вас будет доступ ко всей файловой системе, и вы будете использовать общую папку Documents. Если вы установите его через iTunes или XCode, вы будете использовать личный каталог своих приложений. Приятно хранить файлы в вашем локальном каталоге для резервного копирования.
Эпсилон Прайм

6
objectAtIndex: 0 теперь можно заменить на firstObject
Govind,

3
Или просто [0]через индексный доступ
временное_имя_пользователя

firstObject более безопасен, чем [0] и objectAtIndex: 0
Итачи

1
@Itachi На самом деле в этом случае я предпочитаю исключение, когда в массиве нет объекта. Если результат firstObject- nilнет никакого разумного способа, которым программа могла бы продолжиться, поскольку кое-что в структурах Apple серьезно сломано.
Николай Рюэ

14

Apple рекомендует не полагаться на метод fileExistAtPath:. Часто лучше просто попытаться открыть файл и устранить ошибку, если файл не существует.

Ссылка на класс NSFileManager

Примечание. Попытка предиката поведения на основе текущего состояния файловой системы или конкретного файла в файловой системе не рекомендуется. Это может вызвать странное поведение или расы. Гораздо лучше попытаться выполнить операцию (например, загрузить файл или создать каталог), проверить ошибки и изящно обработать эти ошибки, чем пытаться заранее выяснить, будет ли операция успешной. Для получения дополнительной информации об условиях гонки файловой системы см. «Условия гонки и безопасные операции с файлами» в Руководстве по безопасному кодированию.

Источник: Справочник Apple Developer API

Из руководства по безопасному кодированию.

Чтобы предотвратить это, программы часто проверяют, чтобы временный файл с определенным именем еще не существовал в целевом каталоге. Если такой файл существует, приложение удаляет его или выбирает новое имя для временного файла, чтобы избежать конфликта. Если файл не существует, приложение открывает файл для записи, потому что системная процедура, которая открывает файл для записи, автоматически создает новый файл, если его не существует. Злоумышленник, непрерывно запуская программу, которая создает новый временный файл с соответствующим именем, может (с небольшой настойчивостью и некоторой удачей) создать файл в промежутке между проверкой приложения, чтобы убедиться, что временный файл не существует. и когда он открывает его для записи. Затем приложение открывает файл злоумышленника и записывает в него (помните, системная процедура открывает существующий файл, если он есть, и создает новый файл, только если нет существующего файла). Файл злоумышленника может иметь другие права доступа, чем временный файл приложения, поэтому злоумышленник может прочитать содержимое. Кроме того, у злоумышленника может быть файл уже открыт. Злоумышленник может заменить файл жесткой ссылкой или символической ссылкой на другой файл (файл, принадлежащий злоумышленнику, или существующий системный файл). Например, злоумышленник может заменить файл символической ссылкой на файл системных паролей, чтобы после атаки системные пароли были повреждены до такой степени, что никто, включая системного администратора, не сможет войти в систему. Кроме того, у злоумышленника может быть файл уже открыт. Злоумышленник может заменить файл жесткой ссылкой или символической ссылкой на другой файл (файл, принадлежащий злоумышленнику, или существующий системный файл). Например, злоумышленник может заменить файл символической ссылкой на файл системных паролей, чтобы после атаки системные пароли были повреждены до такой степени, что никто, включая системного администратора, не сможет войти в систему. Кроме того, у злоумышленника может быть файл уже открыт. Злоумышленник может заменить файл жесткой ссылкой или символической ссылкой на другой файл (файл, принадлежащий злоумышленнику, или существующий системный файл). Например, злоумышленник может заменить файл символической ссылкой на файл системных паролей, чтобы после атаки системные пароли были повреждены до такой степени, что никто, включая системного администратора, не сможет войти в систему.


1
Хотя это хороший ответ сам по себе, предоставляя отличный совет. Было бы хорошо увидеть, как это можно реализовать на небольшом примере кода.
SnareChops

8

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

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

4

Swift 2.0

Вот как проверить, существует ли файл с помощью 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)
}

3

проверьте, существует ли файл в пути к документу / 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** 
}

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
}

0

NSURL.h предоставлен - (BOOL)checkResourceIsReachableAndReturnError:(NSError **)errorдля этого

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

Или используя Swift

if let url = URL(fileURLWithPath: NSHomeDirectory()) {
    do {
        let result = try url.checkResourceIsReachable()
    } catch {
        print(error)
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.