2008-10-19 40 views
37

Những năm trước đây khi tôi đã làm việc với C# tôi có thể dễ dàng tạo ra một tập tin tạm thời và có được tên của nó với chức năng này:Làm cách nào để tạo tệp tạm thời với Cocoa?

Path.GetTempFileName(); 

Chức năng này sẽ tạo ra một tập tin với một tên duy nhất trong thư mục tạm thời và trả lại đầy đủ đường dẫn đến tệp đó.

Trong thập niên API Cocoa, điều gần nhất tôi có thể tìm thấy là:

NSTemporaryDirectory 

Tôi có thiếu một cái gì đó rõ ràng hoặc là không có xây dựng theo cách để làm điều này?

+0

Lời cảnh cáo khi sử dụng API C# đó: nó có một không gian tên chỉ có 65k tệp và sẽ ném một ngoại lệ khi đã hết. Điều này đã xảy ra với chúng tôi trong sản xuất - không phải tất cả các chương trình đều cần làm sạch các tệp tạm thời của họ. – fzwo

Trả lời

36

Một cách an toàn là sử dụng mkstemp(3).

+2

@ Chris Hanson: cái gì, không có trang x-man-page: // 3/mkstemp? ;-) –

+10

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

2

Bạn có thể sử dụng mktemp để lấy tên tệp tạm thời.

+5

Có một điều kiện chạy đua trong mktemp (3), tốt hơn nên sử dụng mkstemp (3). –

19

[Lưu ý: Điều này áp dụng cho iPhone SDK, không phải là Mac OS SDK]

Từ những gì tôi có thể nói, các chức năng này không có mặt trong SDK (file unistd.h được mạnh pared xuống khi so với tệp Mac OS X 10.5 chuẩn). Tôi sẽ sử dụng một cái gì đó dọc theo dòng:

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

Không phải là đẹp nhất, nhưng chức năng

+5

Điều này có cùng điều kiện chủng tộc như mktemp (3): Tách việc tạo tên tệp từ khi tạo tệp tạm thời sẽ mở ra một cửa sổ dễ bị tổn thương. Sử dụng mkstemp (3) như Graham Lee gợi ý. –

+0

Xin lỗi, tôi đang ở chế độ iPhone; mkstemp (3) như đề xuất của poster gốc là tốt, nhưng nó sẽ không hoạt động trên iPhone. –

+2

Trên iPhone, mỗi ứng dụng có subtree riêng của hệ thống tập tin. NSTemporaryDirectory() trả về một cái gì đó trong gói ứng dụng. Bạn vẫn chạy đua với chính mình và chống lại bất cứ điều gì khác có quyền ghi vào thư mục tmp của bạn, nhưng tôi nghĩ rằng đó chỉ là các quy trình đặc quyền. – Ken

0

Bạn có thể sử dụng một NSTask-uuidgen để có được một tên file duy nhất, sau đó nối đến một chuỗi từ NSTemporaryDirectory(). Điều này sẽ không hoạt động trên Cocoa Touch. Đó là một chút dài gió mặc dù.

+0

Sử dụng' NSTask' để thực hiện 'uuidgen' là một chút quá mức cần thiết nếu tất cả những gì bạn muốn là UUID. – dreamlax

+0

Lưu ý rằng 10.8+ có lớp NSUUID để tạo UUIDs rời khỏi vùng Ca cao: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUUID_Class/Reference/Reference.html – Jay

12

Mặc dù gần một năm sau đó, tôi nhận thấy vẫn còn hữu ích khi đề cập đến một bài đăng trên blog từ Cocoa With Love của Matt Gallagher. http://cocoawithlove.com/2009/07/temporary-files-and-folders-in-cocoa.html Anh ấy cho biết cách sử dụng mkstemp() cho các tệp và mkdtemp() cho các thư mục, hoàn chỉnh với chuyển đổi NSString.

11

Tôi đã tạo một giải pháp Cocoa nguyên chất theo một danh mục trên NSFileManager sử dụng kết hợp NSTemporary() và ID duy nhất toàn cầu.

Ở đây, file header:

@interface NSFileManager (TemporaryDirectory) 

-(NSString *) createTemporaryDirectory; 

@end 

Và các tập tin thực hiệ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 

Điều này tạo ra một thư mục tạm thời nhưng có thể dễ dàng thích nghi với sử dụng createFileAtPath:contents:attributes: thay vì createDirectoryAtPath: để tạo ra một tập tin để thay thế.

16

Apple đã cung cấp một cách tuyệt vời để truy cập thư mục tạm thời và tạo tên duy nhất cho các tệp tạm thời.

- (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 xem tập tin ::: appdelegate.m

0

Thêm vào @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

Nếu nhắm mục tiêu iOS 6.0 hoặc Mac OS X 10.8 trở lên:

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

Cập nhật cho Swift 3, sao chép trực tiếp từ một sân chơi:

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

Mã này không còn hoạt động, nhưng một phiên bản tương đương thậm chí còn đơn giản hơn: 'URL (fileURLWithPath: NSTemporaryDirectory()). appendingPathComponent (" \ (tiền tố) - \ (UUID()) ")' – Ssswift

+0

Cảm ơn @Ssswift đã cập nhật câu trả lời trong một tiết chi tiết hơn một chút cách thức. –

1

Cách hiện đại để thực hiện điều này là FileManager 's url(for:in:appropriateFor:create:).

Với phương pháp này, bạn có thể chỉ định SearchPathDirectory để nói chính xác loại thư mục tạm thời nào bạn muốn. Ví dụ: .cachesDirectory sẽ tiếp tục tồn tại giữa các lần chạy (càng tốt) và được lưu trong thư viện của người dùng, trong khi .itemReplacementDirectory sẽ có cùng âm lượng với tệp đích.

Các vấn đề liên quan