【问题标题】:iTextSharp Read Text From Single Layer of PDFiTextSharp 从单层 PDF 读取文本
【发布时间】:2018-03-13 17:45:01
【问题描述】:

目前我正在使用自定义 LocationTextExtractionStrategy 从返回 TextRenderInfo[] 的 PDF 中提取文本。我希望能够确定 TextRenderInfo 对象(或 PDFString,TextRenderInfo 的子级)是否出现在特定图层中。我不确定这是否可能。要获取 PDF 中的图层,我使用的是:

Dictionary<string,PdfLayer> layers;
using (var pdfReader = new PdfReader(src))
{
    var newSrc = Path.Combine(["new file location"]);
    using (var stream = new FileStream(newSrc, FileMode.Create))
    {       
        PdfStamper stamper = new PdfStamper(pdfReader, stream);
        layers = stamper.GetPdfLayers();
        stamper.Close();
    }
    pdfReader.Close();
    src = newSrc;
}

为了提取文本,我使用的是:

var textExtractor = new TextExtractionStrategy();
PdfTextExtractor.GetTextFromPage(pdfReader, pdfPageNum,textExtractor);
List<TextRenderInfo> results = textExtractor.Results;

有什么方法可以检查单个 TextRenderInfo 结果是否存在于第一个代码 sn-p 中获得的图层中。任何帮助将不胜感激。

【问题讨论】:

  • 这肯定是可能的,但在我开始回答之前:您在标题中提到您使用 iText 7,但您的代码非常清楚地用 iText 5 (iTextSharp) 编写。 API 相似,但不完全相同,因此我需要知道您想要什么才能回答您的问题。
  • 抱歉,我正在使用 iTextSharp (5),感谢您的帮助。

标签: pdf text itext layer extraction


【解决方案1】:

可以从单个图层中获取内容,但您必须跳过几圈才能解决。具体来说,您将不得不重新创建PdfTextExtractorPdfReaderContentParser 提供的一些逻辑。

public static String GetText(PdfReader reader, int pageNumber, int streamNumber) {
    var strategy = new LocationTextExtractionStrategy();
    var processor = new PdfContentStreamProcessor(strategy);

    var resourcesDic = pageDic.GetAsDict(PdfName.RESOURCES);

    // assuming you still need to extract the page bytes
    byte[] contents = GetContentBytesForPageStream(reader, pageNumber, streamNumber);

    processor.ProcessContent(contents, resourcesDic);
    return strategy.GetResultantText();
}

public static byte[] GetContentBytesForPageStream(PdfReader reader, int pageNumber, int streamNumber) {
    PdfDictionary pageDictionary = reader.GetPageN(pageNum);
    PdfObject contentObject = pageDictionary.Get(PdfName.CONTENTS);
    if (contentObject == null)
        return new byte[0];

    byte[] contentBytes = GetContentBytesFromContentObject(contentObject, streamNumber);
    return contentBytes;
}

public static byte[] GetContentBytesFromContentObject(PdfObject contentObject, int streamNumber) {
    // copy-paste logic from
    // ContentByteUtils.GetContentBytesFromContentObject(contentObject);
    // but in case PdfObject.ARRAY: only select the streamNumber you require
}

如果您特别希望只使用PdfTextExtractorPdfReaderContentParser,并询问返回的TextRenderInfo 以了解它所在的图层,那么我不确定这是否容易实现。这样做有很多问题:

  • TextRenderInfo 不存储该信息,因此您必须对其进行子类化(这是可能的)
  • 您必须重写创建TextRenderInfo 对象的逻辑。这可以通过使用PdfTextExtractorPdfReaderContentParser 为所有文本运算符(TjTJ'")注册自定义IContentOperator 对象来实现
  • 最困难的部分是您已经在 ContentByteUtils.GetContentBytesFromContentObject 中丢失了图层信息 - 所以您需要以某种方式保留它,这会产生一系列问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多