2008-10-19 15 views
37

años cuando estaba trabajando con C# podría fácilmente crear un archivo temporal y obtener su nombre con esta función:¿Cómo se crea un archivo temporal con cacao? Hace

Path.GetTempFileName(); 

Esta función podría crear un archivo con un nombre único en el directorio temporal y devolver la plena camino a ese archivo.

En la década de API Cocoa, lo más parecido que podemos encontrar es:

NSTemporaryDirectory 

Me estoy perdiendo algo obvio o no hay ninguna construida en forma de hacerlo?

+0

Palabra de advertencia al usar esa API C#: tiene un espacio de nombre de solo 65k archivos y arrojará una excepción una vez que se haya agotado. Esto nos ha sucedido a nosotros en producción, no todos los programas limpian diligentemente sus archivos temporales. – fzwo

Respuesta

36

Una forma segura es utilizar mkstemp(3).

+2

@Chris Hanson: qué, no x-man-page: // 3/mkstemp link? ;-) –

+10

http://cocoawithlove.com/2009/07/temporary-files-and-folders-in-cocoa.html –

2

Usted podría utilizar mktemp para obtener un nombre de archivo temporal.

+5

Hay una condición de carrera en mktemp (3), es mejor usar mkstemp (3). –

19

[Nota: Esto se aplica al iPhone SDK, no el Mac OS SDK]

De lo que puedo decir, estas funciones no están presentes en el SDK (el archivo unistd.h se recortaba drásticamente cuando comparado con el archivo estándar Mac OS X 10.5). Me gustaría utilizar algo en la línea de:

[NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"txt"]]; 

No es la más bonita, pero funcional

+5

Esto tiene la misma condición de raza que mktemp (3): Separar la creación del nombre de archivo de la creación de el archivo temporal abre una ventana de vulnerabilidad. Use mkstemp (3) como sugiere Graham Lee. –

+0

Lo siento, estaba en modo iPhone; mkstemp (3) según lo sugerido por el póster original está bien, pero no funcionará en el iPhone. –

+2

En el iPhone, cada aplicación tiene su propio subárbol del sistema de archivos. NSTemporaryDirectory() devuelve algo dentro del paquete de la aplicación. Todavía compites contra ti mismo y contra cualquier otra cosa que tenga permiso de escritura en tu dir de tmp, pero creo que solo son procesos privilegiados. – Ken

0

Se podría utilizar un NSTask a uuidgen para obtener un nombre de archivo único, tiene que poner eso a una cadena de NSTemporaryDirectory(). Esto no funcionará en Cocoa Touch. Sin embargo, es un poco largo.

+0

Usar' NSTask' para ejecutar 'uuidgen' es un poco exagerado si todo lo que quiere es un UUID. – dreamlax

+0

Tenga en cuenta que 10.8+ tiene la clase NSUUID para crear UUID sin dejar la tierra de Cocoa: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUUID_Class/Reference/Reference.html – Jay

11

Creé una solución pura de cacao por medio de una categoría en NSFileManager que usa una combinación de NSTemporary() y una identificación global única.

Aquí el archivo de cabecera:

@interface NSFileManager (TemporaryDirectory) 

-(NSString *) createTemporaryDirectory; 

@end 

Y el archivo de implementación:

@implementation NSFileManager (TemporaryDirectory) 

-(NSString *) createTemporaryDirectory { 
// Create a unique directory in the system temporary directory 
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString]; 
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:guid]; 
if (![self createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:nil]) { 
    return nil; 
} 
return path; 
} 

@end 

Esto crea un directorio temporal, pero podría adaptarse fácilmente para usar createFileAtPath:contents:attributes: en lugar de createDirectoryAtPath: para crear un archivo en su lugar.

16

Apple ha proporcionado una manera excelente para acceder al directorio temporal y la creación de nombres únicos para los archivos temporales.

- (NSString *)pathForTemporaryFileWithPrefix:(NSString *)prefix 
{ 
    NSString * result; 
    CFUUIDRef uuid; 
    CFStringRef uuidStr; 

    uuid = CFUUIDCreate(NULL); 
    assert(uuid != NULL); 

    uuidStr = CFUUIDCreateString(NULL, uuid); 
    assert(uuidStr != NULL); 

    result = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@", prefix, uuidStr]]; 
    assert(result != nil); 

    CFRelease(uuidStr); 
    CFRelease(uuid); 

    return result; 
} 

ENLACE :::: http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009245 ver archivo ::: AppDelegate.m

0

Agregando a @Philipp:

- (NSString *)createTemporaryFile:(NSData *)contents { 
    // Create a unique file in the system temporary directory 
    NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString]; 
    NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:guid]; 
    if(![self createFileAtPath:path contents:contents attributes:nil]) { 
     return nil; 
    } 
    return path; 
} 
8

Si la orientación iOS 6.0 o Mac OS X 10.8 o superior:

NSString *tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]]; 
1

Actualizado para Swift 3, copiada directamente de una Zona de juegos:

import Foundation 

func pathForTemporaryFile(with prefix: String) -> URL { 
    let uuid = UUID().uuidString 
    let pathComponent = "\(prefix)-\(uuid)" 
    var tempPath = URL(fileURLWithPath: NSTemporaryDirectory()) 
    tempPath.appendPathComponent(pathComponent) 
    return tempPath 
} 

let url = pathForTemporaryFile(with: "blah") 
print(url) 
+1

Este código no más tiempo funciona, pero una versión equivalente es aún más simple: 'URL (fileURLWithPath: NSTemporaryDirectory()). appendingPathComponent (" \ (prefijo) - \ (UUID()) ")' – Ssswift

+0

Gracias @Ssswift actualizó la respuesta en un poco más detallado manera. –

1

La forma moderna de hacerlo es FileManager 's url(for:in:appropriateFor:create:).

Con este método, puede especificar un SearchPathDirectory para decir exactamente qué tipo de directorio temporal desea. Por ejemplo, un .cachesDirectory persistirá entre ejecuciones (como sea posible) y se guardará en la biblioteca del usuario, mientras que un .itemReplacementDirectory estará en el mismo volumen que el archivo de destino.

Cuestiones relacionadas