2011-08-22 38 views
2

例如,如果我有很多數據條目存儲在一個文件中,每個文件都有不同的大小,並且我有1000個條目使得文件像100MB大,如果我然後想要刪除文件中間的條目大小爲50KB,如何刪除文件中的空白50KB字節而不移動所有結束字節以填充它?刪除文件中間的字節而不移動結尾?

我使用WINAPI功能,如對這些文件管理:

CreateFileWriteFileReadFileSetFilePointerEx

+6

你的問題沒有道理;你在問如何刪除文件中的一些數據而不縮短它。 – maerics

+0

我確實希望縮短它的時間,我的意思是我每次刪除條目時都無需重新編寫文件就可以做到這一點。例如在訪問時,如果你有一個像1gb大小的海量數據庫,並且只需編輯/刪除1項並保存它,則不需要半個小時就可以將所有項重新寫入文件。 – Kaije

+0

有沒有辦法去做你所要求的東西,而不重寫過去那一點的所有東西(「把它移動」)。 –

回答

7

如果你真的想這樣做,在你進入設置標誌。當你想從你的文件中刪除一個條目,只需使該標誌無效(邏輯刪除)而不用物理刪除它。下次添加條目時,只需查看文件,查找第一個無效條目並覆蓋它。如果全部驗證,則將其追加到最後。這需要O(1)時間來刪除條目和O(n)以添加一個新的條目,假設從磁盤讀取/寫入單個條目是基本操作。

您甚至可以進一步優化它。在文件開始時,存儲位圖1用於無效)。例如,0001000...表示文件中的第4個條目無效。添加條目時,請在位圖中搜索第一個1,並使用Random file I/O(與順序文件I/O相反)將文件指針直接重定向到該條目。以這種方式添加只需要O(1)時間。

哦,我注意到你的評論。如果你想在物理上刪除條目的時候有效地完成它,一個簡單的方法就是swap將文件中最後一個刪除的條目刪除,刪除最後一條,假設條目沒有排序。時間也不錯,對於添加和刪除都是O(1)

編輯:就像喬提到的,this requires that all of your entries have the same size。你可以使用可變長度的條目來實現一個條目,但這將比這裏討論的更復雜。

+1

假設條目的大小是固定的...... – Joe

+0

沒錯。所以是磁盤尋找隨機文件I/O的時間;) –

+0

該位圖有多大?此外,即使使用這個位圖,插入仍然是O(n)。 O(n)可能快於O(n),而不是O(1)。 – IInspectable

1

設A文件的=開始,B =塊以除去的開始,C =塊的端部,以除去

CreateFile與標誌FILE_FLAG_RANDOM_ACCESS

SetFilePointerEx到位置C時,讀出到EOF進緩衝液(此在給定文件大小的情況下可能會是一個很大的緩衝區,請注意巨大的記錄,因爲任何文件IO操作現在都必須分配記錄大小的虛擬內存來執行任何簡單的操作,例如移動)。

複製緩衝器到位置B在文件

現在應該在位置B +的sizeof(塊C)。請致電SetEndOfFile截斷該位置的文件,然後關閉。

請注意,使用memmove函數可以更輕鬆地完成此操作。但是,這需要您將整個文件映射到內存中,進行移動並將其寫回。這對於小文件非常適用,但大於50-100MB的文件我會提醒您有足夠的連續虛擬地址空間。

1

您可以簡單地保持標記未使用的空間,並且在內部碎片超過一定比例的某段時間後,您可以運行一個例程來壓縮文件。通過這種方案,清除速度會很快,但需要定期進行重組。如果您有單獨的文件處理方案,那麼您可以將文件分成幾塊,然後跟蹤空閒塊,並在刪除時將塊標記爲未使用並跟蹤它,稍後在插入時重用它。該方案將取決於文件中的記錄類型,固定或可變長度的記錄。