2010-12-11 117 views
1

我正在使用iTextSharp,並需要生成數十萬個RTF文檔 - 生成的文件在5KB到500KB之間。有沒有辦法讓這個更快? MemoryStream vs FileStream

我在下面列出2種方法 - 原始方法不一定慢,但我想明白爲什麼要寫/從/從文件獲取我需要的輸出字符串。我看到了另一種使用MemoryStream的方法,但它實際上減慢了速度。我基本上只需要輸出的RTF內容,以便我可以在該RTF上運行一些過濾器來清理不必要的格式。帶回數據的查詢非常迅速。要使用原始方法文件生成1000個文件(實際上是創建2000個文件)需要大約15分鐘,與第二種方法相同需要大約25-30分鐘。我運行的結果文件平均大約80KB。

第二種方法有什麼問題嗎?似乎它應該比第一個更快,而不是更慢。

原始的方法:

RtfWriter2.GetInstance(doc, new FileStream(RTFFilePathName, FileMode.Create)); 
doc.Open(); 

    //Add Tables and stuff here 

doc.Close(); //It saves a file here to (RTFPathFileName) 

StreamReader srRTF = new StreamReader(RTFFilePathName); 
string rtfText = srRTF.ReadToEnd(); 
srRTF.Close(); 

    //Do additional things with rtfText before writing to my final file 

的新方法,努力加快速度,但其實這是一半快:

MemoryStream stream = new MemoryStream(); 
    RtfWriter2.GetInstance(doc, stream); 
    doc.Open(); 

    //Add Tables and stuff here 

    doc.Close(); 

    string rtfText = 
    ASCIIEncoding.ASCII.GetString(stream.GetBuffer()); 
    stream.Close(); 


     //Do additional things with rtfText before writing to my final file 

我想我發現這裏的第二種方法: iTextSharp - How to generate a RTF document in the ClipBoard instead of a file

+0

你正在處理的文件有多大?如果它不是很大,那麼不會有太大的區別。如果它很大,那麼你可能不想在內存中處理它,如果它太多降級你的系統。 – phillip 2010-12-11 22:52:07

+0

你好,感謝你的回覆。我需要輸出約400,000個文件 - 介於5KB和500KB之間。我正在使用iTextSharp從SQL查詢生成RTF內容。 – user53885 2010-12-11 22:53:59

+0

重新使用MemoryStream。即分配一次,並將其用於清除其中的內容的所有文件。 – CodesInChaos 2010-12-12 10:08:01

回答

3

您的結果流有多大? MemoryStream在增長時執行大量內存複製操作,因此對於較大的結果,與FileStream相比,通過小塊寫入數據可能花費更長的時間。

若要驗證是否將MemoryStream的初始大小設置爲產生的大小周圍的某個較大值並重新運行代碼。

要修復它,您可以在最初(如果您知道近似輸出的話)預先增大內存流量,或者編寫自己的數據流,以便在增長時使用不同的方案。同樣使用臨時文件可能足以滿足您的目的。

0

就像Alexei說的那樣,它可能是由事實造成的,你每次都在創建MemoryStream,並且每次它隨着它的增長不斷地重新分配內存。嘗試只創建一個流並將其重置爲在每次寫入之前開始。

此外,我認爲stream.GetBuffer()再次返回新的內存,所以嘗試使用相同的StreamReader與您的MemoryStream。

而且看起來你的代碼很容易被平行化,所以你可以嘗試使用Paralel Extesions或者使用TreadPool來運行它。

它似乎有點奇怪,你正在寫你的文本作爲流中的字節,然後讀取這個流作爲字節和轉換爲文本。不可能將文檔直接保存爲文本?

0

MemoryStream不與文件關聯,並且沒有文件名的概念。基本上,你不能那樣做。

你當然不能在它們之間施放;你只能向下投下 - 不能側身投射。可視化:

Stream 
     | 

| | FileStream MemoryStream 您可以通過類型檢查將MemoryStream簡單地轉換爲Stream,並將Stream轉換爲MemoryStream;但從來沒有一個FileStream到一個MemoryStream。這就像說狗是動物,而大象是動物,所以我們可以把狗給大象。

您可以繼承MemoryStream並添加一個Name屬性(即您提供的值),但FileStream和YourCustomMemoryStream之間仍然沒有共同性,並且FileStream不實現預先存在的接口以獲取名稱;所以調用者必須分別明確地處理兩者,或者使用鴨式輸入(可能通過動態或反射)。

另一種選擇(可能更簡單)可能是:將數據寫入臨時文件;從那裏使用FileStream;然後(稍後)刪除該文件。

相關問題