我正在使用此代码将不同的pdf文件页面导入单个文档。当我导入大文件(200页或以上)时,我收到OutOfMemory
例外。我在这里做错了吗?
private bool SaveToFile(string fileName)
{
try
{
iTextSharp.text.Document doc;
iTextSharp.text.pdf.PdfCopy pdfCpy;
string output = fileName;
doc = new iTextSharp.text.Document();
pdfCpy = new iTextSharp.text.pdf.PdfCopy(doc, new System.IO.FileStream(output, System.IO.FileMode.Create));
doc.Open();
foreach (DataGridViewRow item in dvSourcePreview.Rows)
{
string pdfFileName = item.Cells[COL_FILENAME].Value.ToString();
int pdfPageIndex = int.Parse(item.Cells[COL_PAGE_NO].Value.ToString());
pdfPageIndex += 1;
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(pdfFileName);
int pageCount = reader.NumberOfPages;
// set page size for the documents
doc.SetPageSize(reader.GetPageSizeWithRotation(1));
iTextSharp.text.pdf.PdfImportedPage page = pdfCpy.GetImportedPage(reader, pdfPageIndex);
pdfCpy.AddPage(page);
reader.Close();
}
doc.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
答案 0 :(得分:1)
我没有遇到过iTextSharp的OOM问题。是用iTextSharp或其他东西创建的PDF吗?您能否将问题隔离到单个PDF或一组可能已损坏的PDF?下面是创建10个PDF的示例代码,每个PDF包含1,000页。然后它再创建一个PDF,并从这些PDF中随机抽取1页500次。在我的机器上运行需要一段时间,但我没有看到任何内存问题或任何事情。 (iText 5.1.1.0)
using System;
using System.Windows.Forms;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Folder that we will be working in
string WorkingFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Big File PDF Test");
//Base name of PDFs that we will be creating
string BigFileBase = Path.Combine(WorkingFolder, "BigFile");
//Final combined PDF name
string CombinedFile = Path.Combine(WorkingFolder, "Combined.pdf");
//Number of "large" files to create
int NumberOfBigFilesToMakes = 10;
//Number of pages to put in the files
int NumberOfPagesInBigFile = 1000;
//Number of pages to insert into combined file
int NumberOfPagesToInsertIntoCombinedFile = 500;
//Create our test directory
if (!Directory.Exists(WorkingFolder)) Directory.CreateDirectory(WorkingFolder);
//First step, create a bunch of files with a bunch of pages, hopefully code is self-explanatory
for (int FileCount = 1; FileCount <= NumberOfBigFilesToMakes; FileCount++)
{
using (FileStream FS = new FileStream(BigFileBase + FileCount + ".pdf", FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (iTextSharp.text.Document Doc = new iTextSharp.text.Document(PageSize.LETTER))
{
using (PdfWriter writer = PdfWriter.GetInstance(Doc, FS))
{
Doc.Open();
for (int I = 1; I <= NumberOfPagesInBigFile; I++)
{
Doc.NewPage();
Doc.Add(new Paragraph("This is file " + FileCount));
Doc.Add(new Paragraph("This is page " + I));
}
Doc.Close();
}
}
}
}
//Second step, loop around pulling random pages from random files
//Create our output file
using (FileStream FS = new FileStream(CombinedFile, FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (Document Doc = new Document())
{
using (PdfCopy pdfCopy = new PdfCopy(Doc, FS))
{
Doc.Open();
//Setup some variables to use in the loop below
PdfReader reader = null;
PdfImportedPage page = null;
int RanFileNum = 0;
int RanPageNum = 0;
//Standard random number generator
Random R = new Random();
for (int I = 1; I <= NumberOfPagesToInsertIntoCombinedFile; I++)
{
//Just to output our current progress
Console.WriteLine(I);
//Get a random page and file. Remember iText pages are 1-based.
RanFileNum = R.Next(1, NumberOfBigFilesToMakes + 1);
RanPageNum = R.Next(1, NumberOfPagesInBigFile + 1);
//Open the random file
reader = new PdfReader(BigFileBase + RanFileNum + ".pdf");
//Set the current page
Doc.SetPageSize(reader.GetPageSizeWithRotation(1));
//Grab a random page
page = pdfCopy.GetImportedPage(reader, RanPageNum);
//Add it to the combined file
pdfCopy.AddPage(page);
//Clean up
reader.Close();
}
//Clean up
Doc.Close();
}
}
}
}
}
}
答案 1 :(得分:1)
您为每次传递创建了一个新的PdfReader
。这非常低效。而且因为每个人都有PdfImportedPage
,所有这些(可能是多余的)PdfReader
实例都不会被GC控制。
建议:
PdfReader
“打开”。完成给定的阅读器后,请使用PdfCopy.freeReader()
。这几乎肯定会改变页面的添加顺序(可能是非常糟糕的事情)。PdfReader
个实例。完成后再次使用FreeReader ......但是在你退出循环之前,你可能无法释放任何一个。仅缓存可能足以防止内存不足。freeReader()
实例后调用PdfReader
。