2010-08-25 23 views
1

MyClass是關於提供對單個文件的訪問權限。它必須CheckHeader(),ReadSomeData(),UpdateHeader(WithInfo)應該如何設計包裝並提供對單個文件訪問的類?

但由於這個類代表的文件非常複雜,它需要特殊的設計考慮因素。

該文件包含一個潛在的巨大的類似文件夾的樹結構,各種節點類型,並基於以更好地處理碎片塊/細胞。大小通常小於20 MB。 這不是我的設計。

你會如何設計這樣一個班?

  • 將一個〜20MB的流讀入內存?
  • 放在臨時目錄副本,並保持它的路徑屬性?

  • 保持的大事情副本內存和它們公開爲只讀屬性?
  • GetThings()從異常拋出代碼的文件?

這個類(ES)只能由我起初使用,但如果它結束不夠好,我可能開源它。

(這是設計上的問題,而是平臺是.NET和類是關於離線XP註冊表訪問)

回答

1

註冊表的訪問是相當複雜的。你基本上正在閱讀一個大的二叉樹。類設計應該非常依賴存儲的數據結構。只有這樣你才能選擇合適的班級設計。爲了保持靈活性,您應該爲諸如REG_SZ,REG_EXPAND_SZ,DWORD,SubKey等基元建模。Don Syme在他的書Expert F#中介紹了一個關於使用二元組合器進行二進制解析的很好的部分。基本思想是你的對象通過自己知道如何從二進制表示反序列化。當你有其被構造這樣

<部首> <節點1/>
<節點2 > < directory1中>
< /節點2 > < /部首>

字節流

從BinaryReader開始逐字節讀取二進制對象。既然你知道的第一件事一定是頭,你可以將它傳遞給頭對象

public class Header 
{ 
    static Header Deserialize(BinaryReader reader) 
    { 
     Header header = new Header(); 

     int magic = reader.ReadByte(); 
     if(magic == 0xf4) // we have a node entry 
     header.Insert(Node.Read(reader); 
     else if(magic == 0xf3) // directory entry 
     header.Insert(DirectoryEntry.Read(reader)) 
     else 
     throw NotSupportedException("Invalid data"); 

     return header; 
    } 
} 

要保持高性能,你可以如延遲解析數據直到稍後訪問該實例或該實例的特定屬性。

由於Windows中的註冊表可能會變得很大,因此無法一次將其完全讀入內存。你需要將它組裝起來。 Windows應用的一個解決方案是將整個文件分配到頁面緩衝池內存中,該內存可以跨越幾千兆字節,但只有實際訪問的部分從磁盤換出到內存中。這允許Windows以有效的方式處理非常大的註冊表文件。您的閱讀器也需要類似的東西。延遲解析是一個方面,無需讀取數據就可以在文件中跳轉,這對於保持高性能是非常有用的。

更多關於分頁池和註冊表中的相關信息可以在那裏找到: http://blogs.technet.com/b/markrussinovich/archive/2009/03/26/3211216.aspx

你的API的設計將取決於你如何讀取數據保持有效(例如使用memory mapped file並從不同的映射區域讀取)。在.NET 4中,內存映射文件實現已經到來,現在已經相當不錯了,但是OS API的封裝也存在。

你的, 阿洛伊斯·克勞斯

以支持從內存映射文件延遲加載它將使意義不讀字節數組對象,後來分析,但走一步furhter和存儲僅偏移和來自內存映射文件的內存塊的長度。稍後當實際訪問對象時,您可以讀取和反序列化數據。這樣你可以遍歷整個文件並構建一個只包含偏移量和對內存映射文件的引用的對象樹。這應該可以節省大量的內存。

+0

找到像你這樣有用的答案是非常棒的,感謝支持! :)我的第一份草案是一個有getter的getter類,頭部有GetHash等的類,它們不會被緩存,所以類的用戶可以選擇緩存 - 你認爲這有意義嗎?我想稍後很容易維護/重構,因爲我害怕我必須在某個時刻。 – 2010-09-09 04:40:55

+0

其實我認爲這就是你的意思,但只是爲了確保,我目前的想法是,除了它們的序列化二進制表示和從錯誤拋出獲取器返回組件對象外,對象不會保留任何緩存。因此,這意味着將1-50 MB的字節數組保存爲只讀屬性(這樣的大小受益於內存映射文件?)並從中創建對象。 – 2010-09-09 04:46:26

+0

要將字節數組讀入對象是有問題的,因爲您已經使用了相當多的內存。最好只獲取相對於內存映射文件起點的偏移量,並僅在實際訪問對象時讀取數據。 – 2010-09-09 16:13:36

3

這取決於你需要這方面的數據做什麼。如果您只需要一次線性處理它,那麼只需在內存中獲取大文件的性能即可。

然而,如果你需要做的各種事情超越了單一的,線性的分析文件,我會分析數據到一個輕量級的數據庫,如SQLite的,然後在該操作。通過這種方式,您文件的所有結構都將保留,文件上的所有後續操作將更快。

+1

考慮臨時目錄中的文件,如果這些文件突然被刪除,你會怎麼做?你是否會採取措施來優雅地失敗或不值得這樣麻煩? (是否安全地假設文件不會在運行時在應用程序特定的臨時目錄中被隨機刪除?) – 2010-09-05 10:45:29

相關問題