33

我發現這種創建目錄的方式,如果它不存在。但它看起來有點不可思議,我擔心1000次嘗試中有1次會出錯。如果目錄不存在,是否有更安全的方法來創建目錄?

if(![[NSFileManager defaultManager] fileExistsAtPath:bundlePath]) { 
    [[NSFileManager defaultManager] createDirectoryAtPath:bundlePath withIntermediateDirectories:YES attributes:nil error:NULL]; 
} 

只有這種尷尬的方法fileExistsAtPath,它也查找文件,而不僅僅是目錄。但對我而言,危險的是:如果這種情況出現錯誤怎麼辦?我該怎麼辦?什麼是最好的做法,以確保目錄的創建,並且只有當它不存在時才創建?

我知道文件系統操作從來都不安全。設備可能會在電池開始從A到B剷起時突然鬆開電池電源。或者它可能會碰到一個壞點並掛起一秒鐘。也許在很少的情況下,即使沒有目錄,它也會返回YES。簡而言之:我不信任文件系統操作。

我該如何使這絕對安全?

回答

66

實際上,你可以跳過if,儘管蘋果的文件說,該目錄不得存在,如果你正在傳遞withIntermediateDirectories:NO

這使它下降到一個呼叫是唯一真正的。下一步是捕捉任何錯誤:

NSError * error = nil; 
[[NSFileManager defaultManager] createDirectoryAtPath:bundlePath 
          withIntermediateDirectories:YES 
              attributes:nil 
               error:&error]; 
if (error != nil) { 
    NSLog(@"error creating directory: %@", error); 
    //.. 
} 

這將導致一個錯誤,如果目錄已經存在。

+0

太棒了!如果發生錯誤,我該怎麼辦?嘗試再試一次有意義嗎? (至少幾次...?以及如果沒有幫助,該怎麼辦?) – dontWatchMyProfile 2011-05-25 15:00:52

+0

我不知道如果出現錯誤該怎麼辦。這取決於你想要得到多麼奇特。您可以查找特定的錯誤並以不同的方式處理它們,或嘗試創建不同的路徑。也許讓用戶選擇一個不同的? – 2011-05-25 15:17:12

+5

您需要檢查返回值,而不是錯誤指針 – Sven 2013-02-09 08:17:09

3
NSFileManager *fileManager= [NSFileManager defaultManager]; 
if(![fileManager fileExistsAtPath:directory isDirectory:&isDir]) 
    if(![fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:NULL]) 
     NSLog(@"Error: Create folder failed %@", directory); 

來自SO主題here

創建目錄後,可以刷新文件系統,然後檢查是否存在新創建的目錄。這可能是矯枉過正,但你永遠不會有太多的矯枉過正。

+0

你所說的 「刷新文件系統」 是什麼意思? – dontWatchMyProfile 2011-05-25 15:02:01

+0

dontWatchMyProfile:寫入磁盤(或者在這種情況下,FLASH存儲)通常會首先寫入速度更快的RAM,然後在性能和負載允許時將其寫入主存儲器。刷新該緩存或「同步」命令系統「立即寫入緩存的全部內容」。正如OP所言,這很重要,因爲電力已經喪失。 我幾乎沒有關於iPhone和相關設備上的文件IO的信息,但希望有相關的SO線程存在於這裏: http://stackoverflow.com/questions/459537/clear-buffer-cache-on-mac-os-x – 2011-05-25 16:58:38

+2

在第二行和第三行之間,你應該添加一個像這樣的註釋://在這裏,我們切換進程,其他人可以使用剛剛傳遞給fileExistsAtPath的名稱創建一個文件:isDirectory: - 所以這個檢查並不值得這樣做。 – 2012-11-29 18:48:22

1

在SWIFT 2,它看起來是這樣的:

do { 
    try NSFileManager.defaultManager().createDirectoryAtPath(pathURL.absoluteString, withIntermediateDirectories: true, attributes: nil) 
} catch { 
    print(error) 
} 
4

對於雨燕3.0

do { 
    try FileManager.default.createDirectory(atPath: folder, withIntermediateDirectories: true, attributes: nil) 
} catch { 
    print(error) 
} 
相關問題