2012-01-13 6 views
1

WinnovativeのPdfToTextライブラリを評価中で、私に関係することに遭遇しました。NUnitを実行するとサードパーティ製のPdfライブラリがかなり遅くなる

すべてがうまく動作し、私はコンソールアプリケーションを実行している場合すぐに小さな20k以下のpdfからテキストコンテンツを抽出することができます。しかし、NUnit guiから同じコードを呼び出すと、15〜25秒かかります(私はPdfToTextであることを確認しました。テキストを抽出してF10を押して、次の行)。

私は原因を知らないので、どこに責任があるのか​​わからないので、これは私に関係しています。 NUnitやPdfToTextに問題はありますか?私がしたいのは、pdfからテキストを抽出することですが、特定の条件下でこの動作を見るつもりなら、20秒は完全に不合理です。 NUnitを実行しているときだけであれば問題ありませんが、それ以外の場合は別の場所を探す必要があります。あなたは( http://dl.dropbox.com/u/273037/PdfToTextProblem.zip

それは完全なVSソリューション(2010)を使用して、問題を実証する方が簡単ですので、ここでのリンクは、セットアップと実行(NUnitのかPdfToText、あるいはサンプルのPDFをダウンロードする必要はありません)に、それを容易にするためです32ビットマシンで実行している場合は、x86 dllを使用するためにPdfToTextへの参照を変更する必要があります)。

F5を押すだけで、NUnit Guiランナーが読み込まれます。

私はこのライブラリに縛られていませんが、iTextSharpを試してみましたが(2行のコードでは高価です)、Asposeを見ました(私は試していませんでしたが、SaaSライセンス$ 11kです)。しかし、それらは必要な機能が不足しているか、あまりにも高価です。

+0

? iTextの4.1.6バージョンでは、クローズドソーシングソリューションが可能です。 4.1.6はテキスト抽出器を直接持っていませんが、 'PdfReader'と' GetPageContent() 'を使って書くのはあまり難しくありません。 –

+0

PDFは全く複雑ではありません。列や画像はありません。フォーマットされたテキストだけです。しかし、v5.0より前のSourceForgeにiTextSharpのバージョンはありません。私が古いバージョンを手に入れることができると思っていますか?または、Javaバージョン(これは.NETアプリケーション)を使用する必要がありますか。 –

+0

私はここでソースを見つけたようです:http://itextsharp.svn.sourceforge.net/viewvc/itextsharp/tags/。ありがとう、私はそれを試してみましょう! –

答えて

0

(コメントが答えになって)

あなたのPDFファイルはどのように複雑ですか? iTextの4.1.6バージョンでは、クローズドソーシングソリューションが可能です。 4.1.6はテキスト抽出機能を直接持っていませんが、PdfReaderとGetPageContent()を使って書き込むのは難しくありません。

0

以下は、iTextSharp v4.1.6を使用してPDFからテキストを抽出するために使用したコードです。あまりにも冗長であると思われる場合は、それをどのように使用しているか、必要な柔軟性に関係しています。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using iTextSharp.text.pdf; 

namespace ClassLibrary1 
{ 
    public class PdfToken 
    { 
     private PdfToken(int type, string value) 
     { 
      Type = type; 
      Value = value; 
     } 

     public static PdfToken Create(PRTokeniser tokenizer) 
     { 
      return new PdfToken(tokenizer.TokenType, tokenizer.StringValue); 
     } 

     public int Type { get; private set; } 
     public string Value { get; private set; } 
     public bool IsOperand 
     { 
      get 
      { 
       return Type == PRTokeniser.TK_OTHER; 
      } 
     } 
    } 

    public class PdfOperation 
    { 
     public PdfOperation(PdfToken operationToken, IEnumerable<PdfToken> arguments) 
     { 
      Name = operationToken.Value; 
      Arguments = arguments; 
     } 

     public string Name { get; private set; } 
     public IEnumerable<PdfToken> Arguments { get; private set; } 
    } 

    public interface IPdfParsingStrategy 
    { 
     void Execute(PdfOperation op); 
    } 

    public class PlainTextParsingStrategy : IPdfParsingStrategy 
    { 
     StringBuilder text = new StringBuilder(); 

     public PlainTextParsingStrategy() 
     { 

     } 

     public String GetText() 
     { 
      return text.ToString(); 
     } 

     #region IPdfParsingStrategy Members 

     public void Execute(PdfOperation op) 
     { 
      // see Adobe PDF specs for additional operations 
      switch (op.Name) 
      { 
       case "TJ": 
        PrintText(op); 
        break; 
       case "Tm": 
        SetMatrix(op); 
        break; 
       case "Tf": 
        SetFont(op); 
        break; 
       case "S": 
        PrintSection(op); 
        break; 
       case "G": 
       case "g": 
       case "rg": 
        SetColor(op); 
        break; 
      } 
     } 

     #endregion 

     bool newSection = false; 

     private void PrintSection(PdfOperation op) 
     { 
      text.AppendLine("------------------------------------------------------------"); 
      newSection = true; 
     } 

     private void PrintNewline(PdfOperation op) 
     { 
      text.AppendLine(); 
     } 

     private void PrintText(PdfOperation op) 
     { 
      if (newSection) 
      { 
       newSection = false; 
       StringBuilder header = new StringBuilder(); 
       PrintText(op, header); 
      } 

      PrintText(op, text); 
     } 

     private static void PrintText(PdfOperation op, StringBuilder text) 
     { 
      foreach (PdfToken t in op.Arguments) 
      { 
       switch (t.Type) 
       { 
        case PRTokeniser.TK_STRING: 
         text.Append(t.Value); 
         break; 
        case PRTokeniser.TK_NUMBER: 
         text.Append(" "); 
         break; 
       } 
      } 
     } 

     String lastFont = String.Empty; 
     String lastFontSize = String.Empty; 

     private void SetFont(PdfOperation op) 
     { 
      var args = op.Arguments.ToList(); 
      string font = args[0].Value; 
      string size = args[1].Value; 

      //if (font != lastFont || size != lastFontSize) 
      // text.AppendLine(); 

      lastFont = font; 
      lastFontSize = size; 
     } 

     String lastX = String.Empty; 
     String lastY = String.Empty; 

     private void SetMatrix(PdfOperation op) 
     { 
      var args = op.Arguments.ToList(); 
      string x = args[4].Value; 
      string y = args[5].Value; 

      if (lastY != y) 
       text.AppendLine(); 
      else if (lastX != x) 
       text.Append(" "); 

      lastX = x; 
      lastY = y; 
     } 

     String lastColor = String.Empty; 

     private void SetColor(PdfOperation op) 
     { 
      lastColor = PrintCommand(op).Replace(" ", "_"); 
     } 

     private static string PrintCommand(PdfOperation op) 
     { 
      StringBuilder text = new StringBuilder(); 
      foreach (PdfToken t in op.Arguments) 
       text.AppendFormat("{0} ", t.Value); 
      text.Append(op.Name); 
      return text.ToString(); 
     } 

    } 
} 

そして、ここでは、私はそれを呼び出す方法は次のとおりです。

あなたのPDFファイルはどのように複雑な
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using iTextSharp.text.pdf; 

namespace ClassLibrary1 
{ 
    public class PdfExtractor 
    { 
     public static string GetText(byte[] pdfBuffer) 
     { 
      PlainTextParsingStrategy strategy = new PlainTextParsingStrategy(); 
      ParsePdf(pdfBuffer, strategy); 
      return strategy.GetText(); 
     } 

     private static void ParsePdf(byte[] pdf, IPdfParsingStrategy strategy) 
     { 
      PdfReader reader = new PdfReader(pdf); 

      for (int i = 1; i <= reader.NumberOfPages; i++) 
      { 
       byte[] page = reader.GetPageContent(i); 
       if (page != null) 
       { 
        PRTokeniser tokenizer = new PRTokeniser(page); 
        List<PdfToken> parameters = new List<PdfToken>(); 

        while (tokenizer.NextToken()) 
        { 
         var token = PdfToken.Create(tokenizer); 
         if (token.IsOperand) 
         { 
          strategy.Execute(new PdfOperation(token, parameters)); 
          parameters.Clear(); 
         } 
         else 
         { 
          parameters.Add(token); 
         } 
        } 
       } 
      } 

     } 
    } 
} 
関連する問題