2010-03-07 28 views
8

在Windows中,是否可以通過API寫入文件的中間而不覆蓋任何數據,並且之後不必重寫所有內容?寫入到文件中間(不覆蓋數據)

如果可能的話,我相信它會明顯地分割文件;在它成爲嚴重問題之前,我可以做多少次?

如果不可能採取什麼方法/解決方法?在插入點之後重寫所有內容對於大型(即千兆字節)文件來說非常快速。


注意:我不能避免寫中間。把應用程序想象成一個文本編輯器,用於在用戶鍵入內容然後保存的大文件。我也無法將文件分成幾個小文件。

回答

8

如果您需要的臨時結果是一個可以由編輯器以外的其他應用程序使用的平面文件,我不知道有任何方法可以做到這一點。如果您想要生成平面文件,則必須將其從更改點更新到文件末尾,因爲它實際上只是一個順序文件。

但斜體是有充分的理由。如果你可以控制文件格式,你有一些選擇。某些版本的MS Word具有快速保存功能,它們不重寫整個文檔,而是將增量記錄附加到文件末尾。然後,在重新讀取文件時,它會按順序應用所有的增量,以便您最終得到的是正確的文件。如果保存的文件必須立即可用於其他不理解文件格式的應用程序,這顯然不起作用。

什麼我提議存在於商店文件爲文本。使用可以高效編輯和保存的中間表單,然後執行將其轉換爲可用文本文件的步驟(例如,在編輯器退出時)。這樣,用戶可以儘可能多地保存,但耗時的操作不會產生太大的影響。

除此之外,還有一些其他的可能性。

內存映射(而不是加載)文件可能提供的效率會加快速度。你可能仍然需要重寫到文件的末尾,但是它會發生在操作系統的較低級別。

如果您希望快速保存的主要原因是讓用戶繼續工作(而不是讓該文件可用於其他應用程序),則可以將保存操作轉出到單獨的線程並立即將控制權返回給用戶。然後,您需要在兩個線程之間進行同步,以防止用戶修改數據並將其保存到磁盤。

+1

+1用於存儲器映射;但是,對於快速保存的文檔文檔等格式要小心:最終你會得到一個充滿舊數據的巨大文件。這可能是一個問題,因爲(1)浪費磁盤空間和(2)用戶認爲刪除的數據仍然存在,因此顯然爲空的文件可能仍包含敏感信息。IIRC針對這些動機中的一個最新版本的Office(可能是2003,但我不確定)默認情況下,Microsoft會關閉快速保存功能:磁盤比以前快得多,這種技術的缺點超過了優勢。 – 2010-03-08 10:55:12

+0

我認爲從內存Word有一個門檻超過它將寫入真實文件,而不是另一個三角洲,這將解決第一個問題。但是你對敏感數據是正確的,我在文檔中看到過一些並不意味着被看到的東西:-) – paxdiablo 2010-03-08 10:58:11

2

我不確定你的文件的格式,但你可以使它'記錄'的基礎。

  • 將您的數據寫入區塊並給每個區塊一個id。
  • Id可能是文件中的數據偏移量。
  • 在文件的開始處,您可以使用 包含一個包含ID列表的標頭,因此您可以按照 的順序讀取記錄 。
  • 在的「ID列表」結束時,你可以點到另一個位置的文件中(和ID /偏移)存儲IDS

類似的東西到文件系統的另一份名單。

要添加新數據,請在最後附加它們並更新索引(將id添加到列表中)。

你必須弄清楚如何處理刪除記錄和更新。

如果記錄的大小相同,那麼要刪除,可以將其標記爲空,然後再次將其重新用於索引表的適當更新。

0

如果使用.NET 4,如果您有類似編輯器的應用程序,請嘗試使用內存映射文件 - 可能只是票證。像這樣的東西(我沒有把它輸入到VS所以不知道,如果我得到的語法正確):

MemoryMappedFile bigFile = MemoryMappedFile.CreateFromFile(
    new FileStream(@"C:\bigfile.dat", FileMode.Create), 
     "BigFileMemMapped", 
     1024 * 1024, 
     MemoryMappedFileAccess.ReadWrite); 
MemoryMappedViewAccessor view = MemoryMapped.CreateViewAccessor(); 
int offset = 1000000000; 
view.Write<ObjectType>(offset, ref MyObject); 
4

的現實的答案是否定的。你唯一真正的選擇是從修改的角度重寫,或者建立一個更復雜的格式,使用類似索引的東西來告訴如何將記錄按照其預定順序排列。

從純理論的角度來看,你可以在恰當的環境下做到這一點。使用FAT(例如,但大多數其他文件系統至少具有某種程度的相似性),則可以直接操作FAT。 FAT基本上是組成文件的鏈接列表。您可以修改該鏈接列表以在文件中間添加新的羣集,然後將新數據寫入您添加的羣集。

請注意,我說純粹的理論。在像MS-DOS這樣一個完全不受保護的系統下進行這種操作本來就很困難,但卻是合理的。對於大多數較新的系統,進行修改通常都很困難。大多數現代文件系統(相當)比FAT更復雜,這會增加執行的難度。從理論上講,它仍然是可能的 - 事實上,現在它已經徹底失神了,甚至有可能在幾乎合理。

+0

現代操作系統中的直接文件系統修改是braindead:你必須瞭解幾個文件系統是如何工作的(相當困難的事情),爲您的驅動程序編寫您需要的擴展功能,而IFS驅動程序對於「普通」驅動程序編寫者來說也是黑魔法;此外,你會將你的應用程序綁定到幾個文件系統。所有這些對於性能改進往往是微不足道的。 順便說一句,如果中間插入的文本不是集羣的大小,那麼根本沒有性能優勢。 – 2010-03-08 11:03:32

0

可能是最有效的方式做到這一點(如果你真的想這樣做)是調用ReadFileScatter()前後插入點之後讀取數據塊,在FILE_SEGMENT_ELEMENT[3]列表的中間插入新的數據和呼叫WriteFileGather()。是的,這涉及在磁盤上移動字節。但是你將困難的部分留給了操作系統。

0

我注意到了paxdiablo在處理其他應用程序時的回答,以及Matteo Italia對可安裝文件系統的評論。這讓我意識到還有另一個不平凡的解決方案。

使用重新分析點,您可以從基本文件加上增量變量創建一個「虛擬」文件。任何不知道此方法的應用程序都會看到連續的字節範圍,因爲增量通過文件系統過濾器實時應用。對於小型增量(總計< 16 KB),增量信息可以存儲在重新分析點本身;可以將更大的增量放置在替代數據流中。當然不平凡。