2008-10-19 12 views
37

Jahren, als ich mit C# arbeiten konnte ich einfach eine temporäre Datei erstellen und seinen Namen mit dieser Funktion erhalten:Wie erstelle ich eine temporäre Datei mit Cocoa? Vor

Path.GetTempFileName(); 

Diese Funktion eine Datei mit einem eindeutigen Namen in dem temporären Verzeichnis erstellen würde und zurück die volle Pfad zu dieser Datei.

In den Cocoa-API, das nächste, was ich finden kann, ist:

NSTemporaryDirectory 

Bin ich etwas fehlt offensichtlich, oder gibt es nicht in so gebaut, dies zu tun?

+0

Vorsicht bei der Verwendung dieser C# API: Es hat einen Namensraum von nur 65k Dateien und wird eine Ausnahme auslösen, sobald diese erschöpft ist. Dies ist uns in der Produktion passiert - nicht alle Programme säubern fleißig ihre temporären Dateien. – fzwo

Antwort

36

Ein sicherer Weg ist die Verwendung mkstemp(3).

+2

@Chris Hanson: was, keine x-man-page: // 3/mkstemp link? ;-) –

+10

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

2

Sie könnten mktemp verwenden, um einen temporären Dateinamen zu erhalten.

+5

Es gibt eine Race-Bedingung in mktemp (3), besser ist mkstemp (3). –

19

[Anmerkung: Dies gilt für das iPhone SDK, nicht das Mac OS SDK]

Von dem, was ich sagen kann, sind diese Funktionen im SDK nicht vorhanden (die unistd.h Datei herunter drastisch verglichen wird, wenn verglichen mit der Standard-Mac OS X 10.5-Datei). Ich würde etwas entlang der Linien von verwenden:

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

nicht die schönste, aber funktional

+5

Dies hat die gleiche Race Condition wie mktemp (3): Trennung der Erstellung des Dateinamens von der Erstellung von Die temporäre Datei öffnet ein Sicherheitsfenster. Verwenden Sie mkstemp (3), wie Graham Lee vorschlägt. –

+0

Entschuldigung, ich war im iPhone-Modus; mkstemp (3) wie vom ursprünglichen Poster vorgeschlagen, ist in Ordnung, aber es wird nicht auf dem iPhone funktionieren. –

+2

Auf dem iPhone hat jede App einen eigenen Teilbaum des Dateisystems. NSTemporaryDirectory() gibt etwas innerhalb des App-Bundles zurück. Du rennst immer noch gegen dich selbst und gegen alles andere, das Schreibrechte in dein Tmp-Verzeichnis hat, aber ich denke, das sind nur privilegierte Prozesse. – Ken

0

Sie könnten eine NSTask-uuidgen verwenden, um einen eindeutigen Dateinamen zu bekommen, dann ist das von NSTemporaryDirectory() in einen String anhängen. Dies funktioniert bei Cocoa Touch nicht. Es ist jedoch ein bisschen langatmig.

+0

' NSTask' zu verwenden, um 'uuidgen' auszuführen, ist etwas übertrieben, wenn alles was du willst, eine UUID ist. – dreamlax

+0

Beachten Sie, dass 10.8+ über die NSUUID-Klasse verfügt, um UUIDs zu erstellen, ohne das Cocoa-Land zu verlassen: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUUID_Class/Reference/Reference.html – Jay

11

Ich habe eine reine Cocoa-Lösung über eine Kategorie unter NSFileManager erstellt, die eine Kombination aus NSTemporary() und einer global eindeutigen ID verwendet.

Hier wird die Header-Datei:

@interface NSFileManager (TemporaryDirectory) 

-(NSString *) createTemporaryDirectory; 

@end 

Und die Implementierungsdatei:

@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 

Dies schafft ein temporäres Verzeichnis, aber leicht angepasst werden könnte createFileAtPath:contents:attributes: statt createDirectoryAtPath: zu verwenden, anstatt eine Datei zu erstellen.

16

Apple bietet eine hervorragende Möglichkeit, auf das temporäre Verzeichnis zuzugreifen und eindeutige Namen für die temporären Dateien zu erstellen.

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

LINK :::: http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009245 siehe Datei ::: AppDelegate.m

0

zu @Philipp Hinzufügen:

- (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

Wenn iOS 6.0 oder Mac OS X 10.8 oder höher Targeting:

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

für Swift 3, aktualisiert gerade von einem Spielplatz kopiert:

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

Diese Code-Nr Länger funktioniert, aber eine äquivalente Version ist noch einfacher: 'URL (fileURLWithPath: NSTemporaryDirectory()). appendingPathComponent (" \ (Präfix) - \ (UUID()) ") – Ssswift

+0

Dank @Ssswift die Antwort in etwas ausführlicher aktualisiert Weise. –

1

Der moderne Weg dies zu tun ist FileManager 's url(for:in:appropriateFor:create:).

Mit dieser Methode können Sie eine SearchPathDirectory angeben, genau angeben, welche Art von temporären Verzeichnis Sie möchten. Zum Beispiel wird ein .cachesDirectory persistent zwischen Läufen (wie möglich) und in der Bibliothek des Benutzers gespeichert werden, während ein .itemReplacementDirectory wird auf dem gleichen Volume wie die Zieldatei sein.

Verwandte Themen