【问题标题】:Extract Text from Flattenned PDF created with ItextSharp Or PDFSharp从使用 ItextSharp 或 PDFSharp 创建的扁平化 PDF 中提取文本
【发布时间】:2019-10-31 13:46:59
【问题描述】:

我想使用 ItextSharp 从我拥有的某个模板创建的许多 PDF 中检索一些数据。

那些 PDF 被拼合了

FormFlattening = true;

我尝试了许多在互联网上找到的不同方法,但都没有奏效。我收到一条错误消息:

System.InvalidOperationException: 'Stack empty.'

总是当我尝试提取时,通常在以下行,无论策略如何:

string thePage = PdfTextExtractor.GetTextFromPage(reader, i, strategy);

我也尝试了 pdfSharp,但没有运气,也没有关于提取的真实文档。 我还尝试了两个使用 IKVM 的库,但这些库无法在我的项目上运行。

编辑 1:我当前的解决方法是使用 Xpdf 中的 pdftotext.exe,将其作为进程调用,然后读取 txt 文件。这有点慢。

【问题讨论】:

  • 有一些库可以从您的 PDF 文件中提取文本,但要求推荐是 softwarerecs.stackexchange.com 的问题
  • AIUI 您没有使用 PDFsharp 创建 PDF 文件,所以恕我直言,您的标题具有误导性。您没有显示任何 PDFsharp 代码,那么为什么要使用 PDFsharp 标签?
  • 梦想万岁。我说用 iTextSharp 或 pdfsharp 提取。这意味着我只想用其中任何一个来提取数据。我什至在我的回答中说。如您所见,主要问题不是我如何提取这些值。但是为什么他们没有被提取。 mkl 给出了一个很棒的答案。

标签: c# pdf itext pdfsharp


【解决方案1】:

总之

该异常的原因是 PDF 中的错误。一些扁平化到内容中的外观流包含两个结束标记的内容操作,用于单个开始标记的内容操作。在关联的 IContentOperator 实现中,第二个 EMC 会导致异常。通过将该实现包装在一个抑制这些异常的实现中,您可以提取文本。

错误

一些扁平化到内容中的外观流包含两个结束标记内容操作,用于单个开始标记内容操作。

例如以前的外观流扁平化为表单 Xobject Xi8 看起来像这样:

/Tx BMC
q
 1.00 1.00 130.91 29.51 re
W
n
0.00 g

BT
/ArialMT 14.00 Tf
2 10.90 Td
 15.62 TL
(\b\tüü\b) Tj
ET
Q
EMC
EMC 

EMC 操作相关的 IContentOperator 实现只是做了一个

markedContentStack.Pop();

如果是第二个 EMCmarkedContentStack 为空,则会导致 InvalidOperationException

解决方法

您可以通过将 EMC IContentOperator 实现包装在一个抑制这些异常的实现中来防止这种错误情况停止文本提取。

例如使用这个帮助类

public class InvalidOperationExceptionIgnoringWrapper : IContentOperator
{
    public void Invoke(PdfContentStreamProcessor processor, PdfLiteral oper, List<PdfObject> operands)
    {
        try
        {
            WrappedOperator.Invoke(processor, oper, operands);
        }
        catch (InvalidOperationException e)
        {
            Console.Error.WriteLine("Caught InvalidOperationException {0} for {1}", e.Message, oper);
        }
    }

    public IContentOperator WrappedOperator { get; set; }
}

如下:

var pdfReader = new PdfReader(@"SamplePDF.pdf");
int pageNumber = 1;

PdfDictionary pageDic = pdfReader.GetPageN(pageNumber);
PdfDictionary resourcesDic = pageDic.GetAsDict(PdfName.RESOURCES);

ITextExtractionStrategy renderListener = new SimpleTextExtractionStrategy();
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(renderListener);

InvalidOperationExceptionIgnoringWrapper wrapper = new InvalidOperationExceptionIgnoringWrapper();
IContentOperator original = processor.RegisterContentOperator("EMC", wrapper);
wrapper.WrappedOperator = original;

processor.ProcessContent(ContentByteUtils.GetContentBytesForPage(pdfReader, pageNumber), resourcesDic);

var pageText = renderListener.GetResultantText();

现在文本提取时抑制了四个 InvalidOperationExceptions。


这实际上不是最终的修复解决方案,只是解决方法,因为实际错误在PDF中,这些内容流是无效的,因为 PDF 规范明确要求平衡且正确嵌套的标记内容运算符。

【讨论】:

  • 现在这是一个非常清晰和好的答案。非常感谢。
【解决方案2】:

我使用的是商业产品,没有任何问题。 Adobe Acrobat 无法提取任何内容。 大部分底层表单文本是图像,我也没有提取它,但它可能与耦合的 OCR 引擎一起使用。我假设您只想要文本内容而不是 OCR 图像。如果它是 OCR 并提取到 Unicode 文档,那就没问题了。

【讨论】:

  • 是的,我只需要从 C# wpf 项目中获取文本。这就是我的问题。无论我尝试什么,它似乎都不起作用。
猜你喜欢
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-19
相关资源
最近更新 更多