¿Cómo verificar si existe un archivo en la carpeta Documentos?

216

Tengo una aplicación con In-App Purchase, que cuando el usuario compra algo, descarga un archivo html en la carpeta Documentos de mi aplicación.

Ahora debo verificar si este archivo HTML existe, así que si es verdadero, cargue este archivo HTML, de lo contrario cargue mi página html predeterminada.

¿Como puedo hacer eso? Con NSFileManagerno puedo salir de mainBundle...

Obliviux
fuente
"Con NSFileManager no puedo salir de mainBundle", ¿de dónde sacaste esta información errónea?

Respuestas:

521

Swift 3:

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

... le proporciona una URL de archivo del directorio de documentos. Lo siguiente verifica si hay un archivo llamado foo.html:

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

C objetivo:

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

NSString* foofile = [documentsPath stringByAppendingPathComponent:@"foo.html"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
Nikolai Ruhe
fuente
12
Tenga en cuenta que está cargando un archivo desde el directorio de Documentos personales de su aplicación, no el global que encuentra si está liberado. Si instala su aplicación en / Aplicaciones como si fuera una aplicación principal, tendrá acceso a todo el sistema de archivos y usará el directorio de Documentos compartidos. Si lo instala a través de iTunes o XCode, usará el directorio personal de sus aplicaciones. Es bueno almacenar archivos en su directorio local con fines de copia de seguridad.
Epsilon Prime
66
objectAtIndex: 0 ahora se puede reemplazar con firstObject
Govind
3
O simplemente a [0]través del acceso al índice
temporary_user_name
firstObject es más seguro que [0] y objectAtIndex: 0
Itachi
1
@Itachi En realidad, en este caso, prefiero la excepción cuando no hay ningún objeto en la matriz. Si el resultado firstObjectes que nilno hay una manera sensata de cómo podría continuar el programa, ya que algo en los marcos de Apple está seriamente roto.
Nikolai Ruhe
14

Apple recomienda no confiar en el fileExistAtPath: método. A menudo es mejor simplemente intentar abrir un archivo y lidiar con el error si el archivo no existe.

Referencia de clase NSFileManager

Nota: No se recomienda intentar predicar el comportamiento en función del estado actual del sistema de archivos o de un archivo en particular en el sistema de archivos. Hacerlo puede causar un comportamiento extraño o condiciones de carrera. Es mucho mejor intentar una operación (como cargar un archivo o crear un directorio), verificar si hay errores y manejarlos con gracia que tratar de averiguar con anticipación si la operación tendrá éxito. Para obtener más información sobre las condiciones de carrera del sistema de archivos, consulte “Condiciones de carrera y operaciones de archivos seguros” en la Guía de codificación segura.

Fuente: Referencia de la API para desarrolladores de Apple

De la guía de codificación segura.

Para evitar esto, los programas a menudo verifican que un archivo temporal con un nombre específico no exista en el directorio de destino. Si existe dicho archivo, la aplicación lo elimina o elige un nuevo nombre para el archivo temporal para evitar conflictos. Si el archivo no existe, la aplicación abre el archivo para escribir, porque la rutina del sistema que abre un archivo para escribir crea automáticamente un nuevo archivo si no existe ninguno. Un atacante, al ejecutar continuamente un programa que crea un nuevo archivo temporal con el nombre apropiado, puede (con un poco de persistencia y suerte) crear el archivo en el intervalo entre el momento en que la aplicación verificó para asegurarse de que el archivo temporal no existiera y cuando lo abre para escribir. La aplicación luego abre el archivo del atacante y escribe en él (recuerde, la rutina del sistema abre un archivo existente si hay uno, y crea un nuevo archivo solo si no hay un archivo existente). El archivo del atacante puede tener diferentes permisos de acceso que el archivo temporal de la aplicación, por lo que el atacante puede leer el contenido. Alternativamente, el atacante podría tener el archivo ya abierto. El atacante podría reemplazar el archivo con un enlace duro o un enlace simbólico a otro archivo (ya sea propiedad del atacante o un archivo del sistema existente). Por ejemplo, el atacante podría reemplazar el archivo con un enlace simbólico al archivo de contraseña del sistema, de modo que después del ataque, las contraseñas del sistema se hayan dañado hasta el punto de que nadie, incluido el administrador del sistema, pueda iniciar sesión. Alternativamente, el atacante podría tener el archivo ya abierto. El atacante podría reemplazar el archivo con un enlace duro o un enlace simbólico a otro archivo (ya sea propiedad del atacante o un archivo del sistema existente). Por ejemplo, el atacante podría reemplazar el archivo con un enlace simbólico al archivo de contraseña del sistema, de modo que después del ataque, las contraseñas del sistema se hayan dañado hasta el punto de que nadie, incluido el administrador del sistema, pueda iniciar sesión. Alternativamente, el atacante podría tener el archivo ya abierto. El atacante podría reemplazar el archivo con un enlace duro o un enlace simbólico a otro archivo (ya sea propiedad del atacante o un archivo del sistema existente). Por ejemplo, el atacante podría reemplazar el archivo con un enlace simbólico al archivo de contraseña del sistema, de modo que después del ataque, las contraseñas del sistema se hayan dañado hasta el punto de que nadie, incluido el administrador del sistema, pueda iniciar sesión.

orkoden
fuente
1
Si bien esta es una buena respuesta en sí misma, brinda excelentes consejos. Sería bueno ver cómo se podría implementar esto con un pequeño código de ejemplo.
SnareChops
8

Si configura su sistema de archivos de manera diferente o busca una forma diferente de configurar un sistema de archivos y luego verifica si existe un archivo en la carpeta de documentos, aquí hay otro ejemplo. también muestra comprobación dinámica

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
fuente
4

Swift 2.0

Así es como verificar si el archivo existe usando 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
fuente
3

verifique si el archivo existe en el lado de la ruta del documento / 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
fuente
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
fuente
0

NSURL.h siempre - (BOOL)checkResourceIsReachableAndReturnError:(NSError **)errorque lo haga

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

O usando Swift

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