2011-06-25 15 views
0

このコードを使用して、異なるPDFファイルのページを1つのドキュメントにインポートしています。大きなファイル(200ページ以上)をインポートすると、OutOfMemoryの例外が発生します。ここで何か間違っているのですか?iTextSharp Pdfページのインポートメモリの問題

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; 
     } 
    } 

答えて

1

あなたは、各パスのための新しいPdfReaderを作成しています。それはひどく非効率です。そして、あなたがそれぞれからPdfImportedPageを持っているので、それらすべての(おそらく冗長な)PdfReaderインスタンスは決してGC'edされません。

提案:

  1. 二つのパス。最初に、ファイルリスト&ページを作成します。秒は各ファイルに対して順番に処理されるため、一度に1つずつPdfReaderを開くことができます。特定のリーダーで作業が完了したら、PdfCopy.freeReader()を使用してください。これにより、あなたのページが追加される順序が変わることはほとんどありません(おそらく、非常に悪いことです)。
  2. ワンパス。ファイル名に基づいてPdfReaderインスタンスをキャッシュします。 FreeReaderを終了したらもう一度やり直してください...しかし、あなたがループを脱落するまでは、おそらくそれらを解放することはできません。キャッシングだけでは、メモリが不足するのを防ぐのに十分です。
  3. コードをそのまま使用しますが、PdfReaderインスタンスを閉じるとfreeReader()を呼び出します。
1

私はiTextSharpでOOMの問題に遭遇していません。 PDFはiTextSharpなどで作成されていますか?問題を、単一のPDFまたは破損している可能性のある一連のPDFに分離できますか?以下は、それぞれ1000ページのPDFを10個作成するサンプルコードです。次に、もう1つの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(); 
        } 
       } 
      } 

     } 
    } 
} 
+0

Chris、ありがとう – kakopappa

関連する問題