How to reduce memory consumption of PdfPTable with many cells

最后都变了- 提交于 2019-11-26 10:00:59

问题


I\'m creating a PDF using ITextSharp which is composed of a single PdfTable. Unfortunately for a particular data set, I\'m getting an Out of memory Exception due to the large number PdfPCells that are created (I\'ve profiled the memory usage - I\'ve got nearly 1/2 a million cells !)

Is there any way to reduce the memory usage in such a case? I\'ve tried flushing at various points (after each row) and full compression

The PdfWriter is based on a FileStream

Code looks a pretty much like this:

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:


iTextSharp has a very cool interface called ILargeElement that the PdfPTable implements. According to the documentation:

/**
* 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
*/

So all you need to do is after you create your PdfPTable, set the Complete property to false. In your inner loop do some form of counter that every once in a while adds the table and thus clears the memory. Then at the end of the loop set Complete to true and add it one more time.

Below is sample code that shows this off. Without the counter check this code uses about 500MB of RAM on my machine. With the counter check every 1,000 items it goes down to 16MB of RAM. You'll need to find your own sweet spot for the counter and that will depend on how much text you're adding to each cell on average.

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();



回答2:


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();


来源:https://stackoverflow.com/questions/15482142/how-to-reduce-memory-consumption-of-pdfptable-with-many-cells

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!