2012-05-17 66 views
2

寫入文件的一些函數是原子的,因此非常方便,因爲它們可以防止在寫入時發生文件損壞。追加NSString原子文件?

-[NSData writeToFile:atomically:] 
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error; 

的問題是,他們刪除該文件,並用新內容取代它......我需要一個行只是追加到一個巨大的文件。

以原子方式做到這一點的最好方法是什麼,而不是冒着破壞該文件的風險發生?

PS:文件太大而無法在一個字符串中讀取它,更新字符串,然後將巨大的字符串推送到文件系統。

在此先感謝。

回答

5

究其原因,是沒用的功能是因爲原子版本,使文件的副本,它寫的一切,然後重命名新的文件同名的老一個,最後刪除舊文件。因此,原始文件實際上從未被修改,而是被替換爲新文件。

如果你想要快速的原子追加,你可以使用fwritefsync來獲得成功的效果。 fwrite s小於PIPE_BUF(iOS上的4096字節),然後fsync保證爲原子。

下面是一個將執行操作的類別的簡短片段,請注意,它錯過了適當的syscalls錯誤檢查代碼。

@implementation NSData(AppendAtomically) 

- (void)appendToFileAtomic:(NSString *)filePath 
{ 
    NSAssert([self length] < PIPE_BUF, @"Cannot write messages longer than %d atomically", PIPE_BUF); 

    const char *utfpath = [filePath UTF8String]; 

    FILE *f = fopen(utfpath, "ab"); 
    fwrite([self bytes], 1, [self length], f); 
    fsync(fileno(f)); 
    fclose(f); 
} 

@end 
+0

fsync的東西聽起來像我所需要的,謝謝!所以沒有與Objective-C等價的東西,就你所知,它必須是較老的C風格的函數? – MikaelW

+0

您可以輕鬆添加一個類別來隱藏fsync工作。 –

+0

看起來不錯,我會嘗試這種方法,謝謝! – MikaelW

0

有一種方法顯示here和這個堆棧溢出question也顯示類似。

二的方式來做到這一點是:

從文件

NSMutable *data = [NSData dataWithContentsOfFile:yourFilePath]; 
[data appendData:yourNewData]; 
[data writeToFile:yourFilePath]; 

第一個是更適合作爲該文件是hudge獲取數據。

希望這有助於:)

+0

謝謝!但是,這些第一種方法是否能保證原子性?也就是說,如果應用程序在NSFileHandle writedata調用期間突然終止,是否有保證我的文件不會被修改/損壞? – MikaelW

0

看看NSFileHandle。它將允許您打開一個文件進行寫入,將光標定位到文件末尾,然後將數據附加到文件末尾。

+0

謝謝,但對我來說真正重要的是原子性保證。就像,如果應用程序在NSFileHandle writedata調用期間突然終止,是否有保證我的文件不會被修改/損壞? – MikaelW

+1

不幸的是,我不相信有沒有這樣的東西,原子追加到文件。因爲原子性來自寫入副本,然後將副本移到原來的位置。如果你想要原子性,你必須複製你的文件,追加到它,然後移回去。 – mprivat