Comment vérifier si un fichier existe dans le dossier Documents?

216

J'ai une application avec In-App Purchase, que lorsque l'utilisateur achète quelque chose, téléchargez un fichier html dans le dossier Documents de mon application.

Maintenant je dois vérifier si ce fichier HTML existe, donc si c'est vrai, charger ce fichier HTML, sinon charger ma page html par défaut.

Comment je peux faire ça? Avec NSFileManagerje ne peux pas sortir de mainBundle..

Obliviux
la source
"Avec NSFileManager, je ne peux pas sortir de mainBundle" - d'où avez-vous obtenu cette information erronée?

Réponses:

521

Swift 3:

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

... vous donne une URL de fichier du répertoire des documents. Les éléments suivants vérifient s'il existe un fichier nommé foo.html:

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

Objectif c:

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

NSString* foofile = [documentsPath stringByAppendingPathComponent:@"foo.html"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
Nikolai Ruhe
la source
12
Notez que vous chargez un fichier depuis le répertoire Documents personnel de votre application, et non le fichier global que vous trouvez si vous êtes jailbreaké. Si vous installez votre application dans / Applications comme s'il s'agissait d'une application principale, vous aurez accès à l'ensemble du système de fichiers et vous utiliserez le répertoire Documents partagé. Si vous l'installez via iTunes ou XCode, vous utiliserez le répertoire personnel de vos applications. Il est agréable de stocker des fichiers dans votre répertoire local à des fins de sauvegarde.
Epsilon Prime
6
objectAtIndex: 0 peut maintenant être remplacé par firstObject
Govind
3
Ou tout simplement [0]via l' index accès
temporary_user_name
firstObject est plus sûr que [0] et objectAtIndex: 0
Itachi
1
@Itachi En fait, dans ce cas, je préfère l'exception lorsqu'il n'y a aucun objet dans le tableau. Si le résultat firstObjectest nilqu'il n'y a aucun moyen raisonnable de poursuivre le programme, car quelque chose dans les frameworks Apple est sérieusement cassé.
Nikolai Ruhe
14

Apple déconseille de s'appuyer sur la méthode fileExistAtPath :. Il est souvent préférable d'essayer simplement d'ouvrir un fichier et de traiter l'erreur si le fichier n'existe pas.

Référence de la classe NSFileManager

Remarque: Il n'est pas recommandé de tenter de prédire un comportement basé sur l'état actuel du système de fichiers ou sur un fichier particulier du système de fichiers. Cela peut entraîner un comportement étrange ou des conditions de course. Il est de loin préférable de tenter une opération (comme le chargement d'un fichier ou la création d'un répertoire), de rechercher des erreurs et de gérer ces erreurs avec élégance que d'essayer de déterminer à l'avance si l'opération réussira. Pour plus d'informations sur les conditions de concurrence du système de fichiers, voir «Conditions de concurrence et opérations de fichiers sécurisés» dans le Guide de codage sécurisé.

Source: Apple Developer API Reference

Depuis le guide de codage sécurisé.

Pour éviter cela, les programmes vérifient souvent qu'un fichier temporaire portant un nom spécifique n'existe pas déjà dans le répertoire cible. Si un tel fichier existe, l'application le supprime ou choisit un nouveau nom pour le fichier temporaire pour éviter les conflits. Si le fichier n'existe pas, l'application ouvre le fichier pour l'écriture, car la routine système qui ouvre un fichier pour l'écriture crée automatiquement un nouveau fichier s'il n'en existe pas. Un attaquant, en exécutant en continu un programme qui crée un nouveau fichier temporaire avec le nom approprié, peut (avec un peu de persévérance et un peu de chance) créer le fichier dans l'intervalle entre le moment où l'application a vérifié que le fichier temporaire n'existait pas et quand il l'ouvre pour l'écriture. L'application ouvre ensuite le fichier de l'attaquant et y écrit (rappelez-vous, la routine système ouvre un fichier existant s'il y en a un, et crée un nouveau fichier uniquement s'il n'y a pas de fichier existant). Le fichier de l'attaquant peut avoir des autorisations d'accès différentes de celles du fichier temporaire de l'application, afin que l'attaquant puisse ensuite lire le contenu. Alternativement, l'attaquant pourrait avoir le fichier déjà ouvert. L'attaquant pourrait remplacer le fichier par un lien dur ou un lien symbolique vers un autre fichier (appartenant à l'attaquant ou un fichier système existant). Par exemple, l'attaquant pourrait remplacer le fichier par un lien symbolique vers le fichier de mots de passe système, de sorte qu'après l'attaque, les mots de passe système ont été corrompus au point que personne, y compris l'administrateur système, ne peut se connecter. Alternativement, l'attaquant pourrait avoir le fichier déjà ouvert. L'attaquant pourrait remplacer le fichier par un lien dur ou un lien symbolique vers un autre fichier (appartenant à l'attaquant ou un fichier système existant). Par exemple, l'attaquant pourrait remplacer le fichier par un lien symbolique vers le fichier de mots de passe système, de sorte qu'après l'attaque, les mots de passe système ont été corrompus au point que personne, y compris l'administrateur système, ne peut se connecter. Alternativement, l'attaquant pourrait avoir le fichier déjà ouvert. L'attaquant pourrait remplacer le fichier par un lien dur ou un lien symbolique vers un autre fichier (appartenant à l'attaquant ou un fichier système existant). Par exemple, l'attaquant pourrait remplacer le fichier par un lien symbolique vers le fichier de mots de passe système, de sorte qu'après l'attaque, les mots de passe système ont été corrompus au point que personne, y compris l'administrateur système, ne peut se connecter.

orkoden
la source
1
Bien que ce soit une bonne réponse en soi, il fournit d'excellents conseils. Il serait bon de voir comment cela pourrait être mis en œuvre avec un petit exemple de code.
SnareChops
8

Si vous configurez votre système de fichiers différemment ou si vous recherchez une autre façon de configurer un système de fichiers, puis si un fichier existe dans le dossier de documents, voici un autre exemple. afficher également la vérification dynamique

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
la source
4

Swift 2.0

Voici comment vérifier si le fichier existe à l'aide de 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
la source
3

vérifiez si le fichier existe à côté du chemin du document / 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
la source
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
la source
0

NSURL.h a prévu - (BOOL)checkResourceIsReachableAndReturnError:(NSError **)errorde le faire

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

Ou en utilisant Swift

if let url = URL(fileURLWithPath: NSHomeDirectory()) {
    do {
        let result = try url.checkResourceIsReachable()
    } catch {
        print(error)
    }
}
DawnSong
la source