2011-12-09 26 views
6

有很多類似的問題,但沒有什麼回答這個專門搜索後,相當多。這裏所說:在C中截斷文件開頭的最好方法是什麼?

假設我們有文件(可能是二進制,並且更大的太):

abcdefghijklmnopqrztuvwxyz

什麼是最好的方式在C「移動」最右此文件到左側,截斷文件的開頭的部分..所以,例如,「前截斷」 7個字節將改變磁盤上的文件是:

hijklmnopqrztuvwxyz

我必須避免臨時文件,並且寧願不使用大緩衝區來將整個文件讀入內存。我想到的一種可能的方法是將fopen與「rb +」標誌一起使用,並且不斷地來回讀取和寫入以從偏移量開始複製字節到開頭,然後在末尾截斷setEndOfFile。這似乎是很多尋求(可能效率低下)。

另一種方法是打開同一個文件兩次,並將fgetc和fputc與各自的文件指針一起使用。這甚至有可能嗎?

如果還有其他方法,我很樂意閱讀它們。

+0

我結束了兩次打開文件(有兩個文件指針)。這是非常快的(眨眼間約2mb;沒有基準)。我用ftruncate()和fileno()和ftell()。 – snapfractalpop

回答

3

你不必使用巨大的緩衝區大小,內核將爲你做很多工作,但是,從文件中讀取一個完整的緩衝區並寫入更接近開始是如果您無法承擔創建新文件的更簡單工作,將所需內容複製到該文件中,然後將新(臨時)文件複製到舊文件中,請執行此操作。我不排除這樣的可能性:將你想要的文件複製到新文件,然後將新文件替換舊文件或將新文件複製到舊文件將比您描述的混洗進程更快。如果要刪除的字節數是磁盤塊大小而不是7個字節,則情況可能不同,但可能不會。唯一的缺點是複製方法需要更多的中間磁盤空間。

假設您位於POSIX系統上,您的大綱方法將需要使用truncate()ftruncate()將文件縮短到合適的長度。如果您沒有truncate(),那麼您需要進行復制。

請注意,如果你小心,不要打開寫的時候揍文件打開文件兩次將工作確定 - 使用"r+b"模式fopen(),或避免O_TRUNCopen()

+0

感謝您的迴應!要移動的塊的大小可能很大(大約爲兆字節)。我對避免臨時文件的擔心不在於空間,而在於敏感數據的持久性。我想將字節的物理存儲限制在磁盤上的一個位置(儘管複製被刪除,字節仍可能存在)。 順便說一句,我在Linux上。如果我每個字節都來回查詢,內核是否會付出艱辛的努力,如果不是最佳緩衝區,會是什麼?我想知道最後的選擇是否會導致同樣的事情發生。 – snapfractalpop

+0

如果你做單字節讀寫操作,你會做出一些事情(標準I/O或內核 - 或者兩者兼而有之)做很多工作。以千字節大小的塊(比如1,2,4,8,16,32個KiB塊)工作會更有效率,不會給所有環境中最貧困的環境帶來壓力。內核將爲你處理對齊等 - 幸運的是。 –

+0

好的。再次感謝! – snapfractalpop

4

你可以把mmap這個文件存入內存然後把內容移除。你將不得不分別截斷文件。

+0

所以,步驟是: 1)mmap 2)memmove 3)un-mmap(這是否存在?) 4)truncate ? – snapfractalpop

+1

@snapfractalpop [相關示例](http://pastebin.com/s1vSCvxA)。該解決方案有可能非常快,但文件大小受地址空間大小的限制。您將無法在32位系統上截斷大(> 4GB)文件。 –

+2

@Banthar:比這更糟糕:你需要一個足夠大的進程地址空間的連續部分。這可能遠遠低於4GB,具體取決於碎片和其他內存分配情況。 – Joe

相關問題