2012-08-31 33 views
0

是否可以刪除文件的一部分(假設從一開始到另一半),而不必使用其他文件?如何剪切文件而不使用其他文件?

謝謝!

+0

你接受使用RAM嗎?我可以在內存中讀取0.5的空洞文件,將其刪除,然後再寫入我讀過的0.5個數據。 – 2012-08-31 22:11:17

+1

我想這是OP試圖避免的。 – jrok

+1

簡答:不,(至少大部分)文件系統不支持。關於你所能做的就是創建一個副本(在相同或不同的文件中),以避免你不想要的部分。 –

回答

2

簡而言之,不,大多數文件系統不會嘗試支持那樣的操作。

給你留下兩種選擇。顯而易見的是創建數據的副本,而不需要的部分。您可以在原地(即在相同文件中移動數據)或使用輔助文件(通常將數據複製到新文件),然後執行類似將新文件重命名爲舊名稱的操作。

另一個主要選擇是簡單地重新構造您的文件和數據,因此您根本不必擺脫舊數據。例如,如果你想保留一個進程中最新的N個數據量,你可以將文件的結構(大部分)作爲一個循環緩衝區,在開始處有幾個「指針」告訴你頭部和尾部點,所以你知道從哪裏讀取數據/寫入數據。使用這樣的結構,您不會刪除或刪除舊數據,只需根據需要覆蓋它即可。

1

如果您有足夠的內存,請將其內容完全讀取到內存中,將其複製迴文件的前端,然後截斷該文件。

如果您沒有足夠的內存,請複製塊,並且僅在完成截斷文件時完成。

+0

但是該文件可能太大而無法在內存中複製,即使是需要很長時間的阻塞 – 2012-08-31 22:14:07

+0

在塊中讀取時,內存不是問題。時間問題不是內存,而是I/O - 較大的文件是較長的進程。 – Grzegorz

3

是的,這是可能的,但你仍然必須重寫大部分文件。

課文大意如下:

open the file 
beg = find the start of the fragment to be removed 
len = length of the fragment to be removed 
blocksize = 4096 -- example block size, may be any 
datamoved = 0 
do { 
    fseek(pos +len +datamoved); 
    if(endoffile) return; -- finished! 
    actualread = fread(buffer, blocksize) 
    fseek(pos + datamoved) 
    fwrite(buffer, actualread) 
    datamoved += actualread 
} 

和循環之後的最後一步是「截斷」的文件到POS + datamoved大小。如果底層文件系統不處理'truncatefile'操作,那麼你必須重寫..但大多數文件系統和庫支持。

+1

僅供參考:在傳統的HDD或Floppys或ZIP驅動器中,以這種方式刪除文件碎片可能比將文件重寫爲新文件慢得多,因爲尋回回寫可能導致驅動器的頭部,以及尋求:)可能,但不一定。此外,如果您可以將您的代碼綁定到特定的文件系統,您可能會發現一些低級操作,可能實際上從文件的中間插入/重新排序/刪除BLOCK/INODE - 那麼您只需移動少量數據,但這是相當複雜的事情來執行.. – quetzalcoatl

相關問題