2013-03-18 129 views
2

我使用ITextSharp創建一個PDF,它由一個PdfTable組成。不幸的是,對於一個特定的數據集,由於創建了大量的PdfPCells,我得到了內存不足(我已經分析了內存使用情況 - 我已經獲得了將近1/2萬個單元!)如何減少與許多單元格PdfPTable的內存消耗

在這種情況下,有什麼辦法可以減少內存使用量嗎? 我試過在不同的點沖洗(每行之後)和全壓縮

的PdfWriter是基於一個FileStream

代碼看起來非常像這樣:

Document document = Document(); 
FileStream stream = new FileStream(fileName,FileMode.Create);         
pdfWriter = PdfWriter.GetInstance(document, stream); 
document.Open(); 
PdfPTable table = new PdfPTable(nbColumnToDisplay); 
foreach (GridViewRow row in gridView.Rows) 
{ 
    j = 0; 
    for (int i = 0; i < gridView.HeaderRow.Cells.Count; i++) 
    { 
     PdfPCell cell = new PdfPCell(new Phrase(text)); 
     table.AddCell(cell); 
    } 
} 
document.Add(table); 
document.Close(); 
+1

你能分享你的代碼嗎? – 2013-03-18 16:39:56

回答

4

iTextSharp的有非常酷的界面ILargeElementPdfPTable實現。根據文檔:

/** 
* Interface implemented by Element objects that can potentially consume 
* a lot of memory. Objects implementing the LargeElement interface can 
* be added to a Document more than once. If you have invoked setCompleted(false), 
* they will be added partially and the content that was added will be 
* removed until you've invoked setCompleted(true); 
* @since iText 2.0.8 
*/ 

因此,所有你需要做的是您創建PdfPTable之後,Complete屬性設置爲false。在你的內循環中做一些形式的計數器,每隔一段時間添加一次表格,從而清除內存。然後在循環結束時將Complete設置爲true並將其添加一次。

以下是顯示此功能的示例代碼。沒有計數器檢查,這個代碼在我的機器上使用了大約500MB的RAM。隨着計數器檢查每1,000個項目它下降到16MB的RAM。您需要爲櫃檯找到自己的甜蜜點,這取決於您平均向每個單元格添加多少文本。

string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "table.pdf"); 
Document document = new Document(); 
FileStream stream = new FileStream(fileName, FileMode.Create); 
var pdfWriter = PdfWriter.GetInstance(document, stream); 
document.Open(); 

PdfPTable table = new PdfPTable(4); 
table.Complete = false; 
for (int i = 0; i < 1000000; i++) { 
    PdfPCell cell = new PdfPCell(new Phrase(i.ToString())); 
    table.AddCell(cell); 
    if (i > 0 && i % 1000 == 0) { 
     Console.WriteLine(i); 
     document.Add(table); 
    } 
} 
table.Complete = true; 
document.Add(table); 
document.Close(); 
+0

+1 - 看起來不錯,但只適用於版本5.xxx。我們在4.5,嘗試升級,但我失去了我的RTFWriter,因爲它不再是圖書館的一部分! :-( – 2013-03-19 09:25:50

+1

您可以嘗試移植此代碼:https://code.google.com/p/itextsharpmplmaint/source/browse/itext/iTextSharp/text/rtf/?r=49a4718630aae3eec4dee5180f0068381c5011b7#rtf – 2013-03-19 13:10:26

+1

此方法適用於iTextSharp 4.1.2使用ILargeElement接口有table.ElementComplete屬性 – dlxeon 2016-01-14 13:36:54

0

PdfPTable pdftbale = new PdfPTable(gridview.HeaderRow.Cells.Count);

foreach (TableCell tabhead in gridview.HeaderRow.Cells) 
    { 
     PdfPCell pdfcell1 = new PdfPCell(new Phrase(tabhead.Text)); 
     pdftbale.AddCell(pdfcell1); 
    } 

    foreach (GridViewRow gd in gridview.Rows) 
    { 
     foreach (TableCell tab in gd.Cells) 
     { 
      PdfPCell pdfcell = new PdfPCell(new Phrase(tab.Text)); 
      pdftbale.AddCell(pdfcell); 
     } 
    } 

    iTextSharp.text.Document pdfDocument = new iTextSharp.text.Document(PageSize.A4, 10f, 10f, 10f, 10f); 
    PdfWriter.GetInstance(pdfDocument, new FileStream(Server.MapPath("~/pdf/" + DateTime.Now.ToString("ddMMyyyyhhmmss") + ".pdf"), FileMode.Create)); 
    pdfDocument.Open(); 
    pdfDocument.Add(pdftbale); 
    pdfDocument.Close(); 
+1

歡迎來到SO並感謝您的回答,您可以給您的代碼添加一點解釋嗎? – Francesco 2016-04-27 09:12:43