如何减少许多细胞PdfPTable的内存消耗 [英] How to reduce memory consumption of PdfPTable with many cells

查看:177
本文介绍了如何减少许多细胞PdfPTable的内存消耗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建使用它是由一个单一的PdfTable的iTextSharp的PDF文件。不幸的是,一个特定的数据集,我发现了一个内存溢出异常是由于所创建的大量PdfPCells(我异形的内存使用情况 - 我有近1/2的百万个细胞!)



有什么办法来减少这种情况下,内存使用情况?
我已经试过在不同的点冲洗(每行后),全压缩



PdfWriter是基于一个FileStream



代码看起来非常像这样的:

 文档文件=文件(); 
的FileStream流=新的FileStream(文件名,FileMode.Create);
pdfWriter = PdfWriter.GetInstance(文件,流);
document.Open();
PdfPTable表=新PdfPTable(nbColumnToDisplay);
的foreach(GridViewRow行gridView.Rows)
{
J = 0;
的for(int i = 0; I< gridView.HeaderRow.Cells.Count;我++)
{
PdfPCell电池=新PdfPCell(新乐句(文本));
table.AddCell(单元);
}
}
document.Add(表);
document.Close();


解决方案

iTextSharp的有一个叫做的 ILargeElement PdfPTable 工具。根据文档:

  / **通过Element对象来实现
*接口,可以潜在消费
*大量的内存。实施LargeElement接口可以
*的对象被添加到文档超过一次。如果你已经调用setCompleted(假),
*,他们将部分添加添加的内容将是
*删除,直到你调用setCompleted(真);
* @Since的iText 2.0.8
* /



因此​​,所有你需要要做的就是创建您 PdfPTable ,将完成属性设置为false后。在你的内循环做某种形式的计数器,在每隔一段时间,增加了表格,从而清除内存。然后在循环集的末尾完成为true,并将其添加一次。



下面是示例代码显示这一关。如果没有计数器检查该代码使用了我的机器上的500MB的RAM。随着计数器检查每1,000个项目就下降到16MB内存。你需要找到自己的甜蜜点计数器,这将取决于你多少文本增加,平均每个单元格。

 字符串文件名= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),table.pdf); 
文档的文档=新的文件();
的FileStream流=新的FileStream(文件名,FileMode.Create);
VAR pdfWriter = PdfWriter.GetInstance(文件,流);
document.Open();

PdfPTable表=新PdfPTable(4);
table.Complete = FALSE;
的for(int i = 0; I< 1000000;我++){$​​ B $ B PdfPCell电池=新PdfPCell(新乐句(i.ToString()));
table.AddCell(单元);
如果(ⅰ大于0&放大器;&放大器;则i%1000 == 0){
Console.WriteLine(ⅰ);
document.Add(表);
}
}
table.Complete = TRUE;
document.Add(表);
document.Close();


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

解决方案

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

这篇关于如何减少许多细胞PdfPTable的内存消耗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆