2010-04-27 43 views
0

我需要提示如何將多個NSData塊寫入單個文件。在塊中使用NSURLConnection下載文件。每個塊都在單獨的NSOperation線程中下載。隨着塊完成下載,它們需要寫入文件,所以組合結果就是下載的文件。將多個NSData塊寫入文件

管理返回的NSData並將其寫入單個文件的最佳方式是什麼?

+1

可能的重複http://stackoverflow.com/questions/1255295/append-nsdata-to-a-file-in-objective-c – 2010-04-27 14:36:58

+0

@Martin戈登:我不認爲這是重複的。它可能只是措辭,所以我不明白它,但它聽起來是他在其他線程上下載離散塊,然後必須重新創建該文件。如果這是真的,那麼因爲文件不會正確排序(因爲任何塊可能會在其他塊之前完成),因此在塊進入時追加塊將不起作用。 – 2010-04-27 15:00:24

+0

正如Jason Cocoa所說,每個塊(任意大小)的文件都是在一個單獨的線程中下載的(因此在寫入文件時調度可能是一個問題)。所有的數據都需要合併成一個文件。但由於文件大小可能超過100MB,因此寫入數據並不保存在內存中非常重要。 – MikeM 2010-04-27 16:31:07

回答

1

將每個塊寫入單獨的文件。然後下載最後一個塊時,按正確的順序將每個文件連接成一個大文件。

+0

你可以提供更多關於如何完成的細節。我有多個文件後,如何將所有內容附加到單個文件? – MikeM 2010-04-28 02:57:32

+3

您可以使用循環與NSInputStream和initWithFileAtPath:一次讀取一個小緩衝區(4 kb是理想的),並使用+ [NSOutputStream outputStreamToFileAtPath:append:]寫入新文件。 – lucius 2010-04-28 16:06:31

1

假設你知道最終的數據大小是多少,並且你想堅持Foundation類/ Objective-C,你可以創建一個可以在這些操作中共享的NSMutableData實例。當一個操作完成它的塊時,它應該鎖定一些共享互斥體,將其完成的下載文件寫入NSMutableData對象的相應位置,然後解鎖共享互斥體。

所有操作加入後,只需使用NSData類上的writeToFile:convenience方法將可變數據寫入文件即可。如果你更精通C/BSD,你也可以將該文件創建爲mmap並簡單地寫入它。由於映射中的所有數據都將離散秒,因此可以在不鎖定互斥鎖的情況下編寫數據。所有操作加入後,您可以刪除mmap並關閉文件。

+0

C/BSD方法可能是這樣做的一種方式,但我正在尋找Objective-C的答案。你給的東西會起作用,但我關心的是文件的大小,並保存在內存中,直到下載完成。文件大小將超過100MB。 – MikeM 2010-04-27 15:14:59

+0

@ user326943:如果您擔心文件大小,我認爲mmap是要走的路。另一種選擇是簡單地打開文件句柄並查找/寫入文件。這個選項顯然需要鎖定,因爲寫入閃存器件的速度很慢,所以線程可能會加入很多爭用。 – 2010-04-27 16:46:02

+0

@ user326943:另一個所有Cocoa選項可能會讓操作寫入一個臨時文件,該文件的名稱與主文件中塊的序列一樣有意義。一旦所有的操作都被加入,你可以將所有這些臨時文件合併到最終的大文件中,並在一個線程中以塊的形式讀寫它們。 – 2010-04-27 16:47:30

10

沒有必要通過創建一個大型的NSMutableData對象來消耗內存(無論如何,因爲內存不足,無論如何都無法進行大量下載),也不需要浪費時間創建大量小文件並對其進行拼接(可以需要很長時間才能處理大文件,iDevice磁盤IO不是很快)。

只需創建一個NSFileHandle並用它給每個NSData對象寫入文件的結尾,因爲他們進來,

NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; 
[handle seekToEndOfFile]; 
[handle writeData:dataPiece]; 
[handle closeFile]; 

您需要先創建該文件,雖然這樣就可以打開它與NSFileHandle。要做到這一點,您可以使用以下內容編寫第一個NSData文件,然後使用文件句柄編寫其餘的文件。

[dataPiece writeToFile:filePath atomically:YES]; 

編輯:其實我只是重新閱讀的問題,並意識到你是使用單獨的線程下載塊,使他們可以不按順序完成,所以我的解決辦法是行不通的。我回答的那一天一定很累,並且跳過它。但是,希望我的回答至少可以幫助其他人按順序或單線程下載塊。

+0

它幫助了我!謝謝! – 2012-04-20 14:21:12

+0

有沒有辦法將數據寫入文件中的特定位置? – 2014-06-23 11:20:25

+0

而不是調用seekToEndOfFile,找到你想寫的地方。 – 2014-06-23 23:01:23