【问题标题】:Reading a table or cell value in a pdf file using java?使用java读取pdf文件中的表格或单元格值?
【发布时间】:2015-02-02 11:36:27
【问题描述】:

我已经通过 Java 和 PDF 论坛从 pdf 文件中的表格中提取文本值,但除了 JPedal 之外找不到任何解决方案(它不是开源和许可的)。

所以,我想知道任何开源 API,如 pdfbox、itext 以实现与 JPedal 相同的结果。

参考。示例:

【问题讨论】:

  • 我记得很多个月前使用过一个名为 iText 的免费库...itextpdf.com
  • iText 也被许可作为开源。请参阅Is iText Java library free of charge or have any fees to be paid? 了解更多信息。话虽这么说,您需要先回答这个反问题,然后才能帮助您:PDF 是否为 Tagged PDF?如果没有,则 PDF 内没有表格。观看this video 以了解有关结构的更多信息。人眼可以看到一张桌子,机器只能看到没有任何结构的线条和字符。
  • 如何从pdf文件中的表格中找到文本值
  • @mkl - 通过提供 X 和 Y 坐标,JPedal 以这种方式实现了逻辑。
  • 其他人也可以。

标签: java itext pdfbox jpedal


【解决方案1】:

在 cmets 中,OP 澄清说他从 pdf 文件中的表中找到 文本值他想要提取

通过提供 X 和 Y 坐标

因此,虽然这个问题最初听起来像是从 PDF 中通用提取表格数据(至少可能很困难),但实际上它本质上是关于从坐标给定的页面上的矩形区域中提取文本。

这可以使用您提到的任何一个库(当然还有其他库)。

iText

要限制要从中提取文本的区域,可以在FilteredTextRenderListener 中使用RegionTextRenderFilter,例如:

/**
 * Parses a specific area of a PDF to a plain text file.
 * @param pdf the original PDF
 * @param txt the resulting text
 * @throws IOException
 */
public void parsePdf(String pdf, String txt) throws IOException {
    PdfReader reader = new PdfReader(pdf);
    PrintWriter out = new PrintWriter(new FileOutputStream(txt));
    Rectangle rect = new Rectangle(70, 80, 490, 580);
    RenderFilter filter = new RegionTextRenderFilter(rect);
    TextExtractionStrategy strategy;
    for (int i = 1; i <= reader.getNumberOfPages(); i++) {
        strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), filter);
        out.println(PdfTextExtractor.getTextFromPage(reader, i, strategy));
    }
    out.flush();
    out.close();
    reader.close();
}

ExtractPageContentArea 示例来自 iText in Action,第 2 版)

但请注意,iText 基于内容流中的基本文本块提取文本,而不是基于此类块中的每个单独的字形。因此,如果只有最小部分在该区域中,则整个块都会被处理。

这可能适合您,也可能不适合您。

如果您遇到提取的内容比您想要的多的问题,您应该事先将块拆分为它们的构成字形。 This stackoverflow answer 解释了如何做到这一点。

PDFBox

要限制要从中提取文本的区域,可以使用PDFTextStripperByArea,例如:

PDDocument document = PDDocument.load( args[0] );
if( document.isEncrypted() )
{
    document.decrypt( "" );
}
PDFTextStripperByArea stripper = new PDFTextStripperByArea();
stripper.setSortByPosition( true );
Rectangle rect = new Rectangle( 10, 280, 275, 60 );
stripper.addRegion( "class1", rect );
List allPages = document.getDocumentCatalog().getAllPages();
PDPage firstPage = (PDPage)allPages.get( 0 );
stripper.extractRegions( firstPage );
System.out.println( "Text in the area:" + rect );
System.out.println( stripper.getTextForRegion( "class1" ) );

(来自 PDFBox 1.8.8 示例的ExtractTextByArea

【讨论】:

  • 嗨,mkl,由于无法找到哪些数据表示哪个列,因此使用此解决方案会截断空格。有没有办法保留空白?
  • 对于 iText,请查看 this answer,它解释了如何基于 LocationTextExtractionStrategy 创建文本提取策略,该策略试图通过在必要时插入空格来反映 PDF 的水平布局。 PDFBox 应该可以使用等效技术。
  • @sgelle This answer 解释了如何以尝试通过在必要时插入空格来反映 PDF 的水平布局的方式使用 PDFBox 文本提取。
【解决方案2】:

试试PDFTextStream。至少我能够识别列值。早些时候,我使用 iText 并陷入了定义策略的困境。很难。

此 api 通过放置更多空格来分隔列单元格。它的固定。你可以把逻辑。 (这在 iText 中是缺失的)。

import com.snowtide.PDF;
import com.snowtide.pdf.Document;
import com.snowtide.pdf.OutputTarget;

public class PDFText {
    public static void main(String[] args) throws java.io.IOException {
        String pdfFilePath = "xyz.pdf";

        Document pdf = PDF.open(pdfFilePath);
        StringBuilder text = new StringBuilder(1024);
        pdf.pipe(new OutputTarget(text));
        pdf.close();
        System.out.println(text);
   }
}

Question has been asked related to this on stackoverflow!

【讨论】:

    猜你喜欢
    • 2015-06-18
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2022-11-13
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多