Java 如何在使用PDFBox从PDF提取数据时用单词替换空格

Java 如何在使用PDFBox从PDF提取数据时用单词替换空格,java,pdf,pdfbox,Java,Pdf,Pdfbox,我想用一个词替换任何空列;例如,在提取Pdf数据时使用单词BLK 下表是预期表和实际结果的示例 原始表格 +--------------------------------------+ |# |NAME |TEL |GENDER | |---------------------------|----------| |1 |JOHN |096587498 |M | |2 |VILLA | |F

我想用一个词替换任何空列;例如,在提取Pdf数据时使用单词BLK

下表是预期表和实际结果的示例

原始表格

+--------------------------------------+
|# |NAME        |TEL        |GENDER    |
|---------------------------|----------|
|1 |JOHN        |096587498  |M         |
|2 |VILLA       |           |F         |
+--------------------------------------+
预期结果

# NAME TEL GENDER
1 JOHN 096587498 M
2 VILLA BLK F
# NAME TEL GENDER
1 JOHN 096587498 M
2 VILLA F
实际结果

# NAME TEL GENDER
1 JOHN 096587498 M
2 VILLA BLK F
# NAME TEL GENDER
1 JOHN 096587498 M
2 VILLA F
实际结果来自类PDFTextStripper

捕获pdf
PDFTextStripper看不到PDF中的图形行,它只看到文本字符。因此,在您的第2行中,可以看到“2”、“Villa”和“F”之间有间隙。因此,单凭这门课,你不会得到你想要的

通常,使用PDFBox可以使用以下选项:

  • 您可以首先尝试通过解析页面的矢量图形指令来识别PDF中的表格单元格区域,然后逐个单元格提取文本单元格

    为此提供了概念证明。注意:这个答案集中在该问题的OP提供的示例文档上。特别是,它期望线被绘制为薄填充矩形;对于一般解决方案,需要扩展收集表行的代码,以便识别以其他方式绘制的行

    这种方法显然需要将表的行和列按行(或者按扩展,或者按背景色或类似的方式)划分;情况并非总是如此

    对于示例文档,代码是开箱即用的:

    [A1]#
    [A2]姓名
    [A3]电话
    [A4]性别
    [B1]1
    [B2]约翰
    [B3]096875959
    [B4]M
    [C1]2
    [C2]别墅
    [C3]
    [C4]F
    
    (test
    testExtractBoxedTextStestWPhroma的输出

  • 您可以提取试图反映PDF布局的文本。如果您知道相关表格的总体布局(n列从这里到那里…),则可以导出表格单元格内容

    为布局感知文本提取提供概念证明。注意,代码是基于PDFBox 1.8.x的,可能需要进行一些修改

    这种方法需要了解表列布局;这并不总是被给予的

    对于示例文档,代码是开箱即用的:

    #姓名电话性别
    1约翰096875959米
    F别墅2号
    
    (test
    testExtractTestWPhroma的输出

  • 对于标记的PDF,您可以尝试提取文本,包括反映表结构的标记(如果标记正确)

    当您的示例文档被标记时,我将在下面展示一个快速的概念证明

    这种方法要求PDF正确标记;情况并非总是如此

利用标签提取内容 如果您的PDF已正确标记,则可以提取包含标记标记的内容,如下所示:

PDDocument document = PDDocument.load(SOURCE);

Map<PDPage, Map<Integer, PDMarkedContent>> markedContents = new HashMap<>();

for (PDPage page : document.getPages()) {
    PDFMarkedContentExtractor extractor = new PDFMarkedContentExtractor();
    extractor.processPage(page);

    Map<Integer, PDMarkedContent> theseMarkedContents = new HashMap<>();
    markedContents.put(page, theseMarkedContents);
    for (PDMarkedContent markedContent : extractor.getMarkedContents()) {
        theseMarkedContents.put(markedContent.getMCID(), markedContent);
    }
}

PDStructureNode root = document.getDocumentCatalog().getStructureTreeRoot();
showStructure(root, markedContents);
(辅助方法)

示例PDF的输出


#

名称

电话

性别

1.

约翰

096875959

M

2.

别墅

F

您可以识别空单元格:

<TD>
<P>

</P>
</TD>

此概念验证提取到标准输出。显然,您可以选择在字符串生成器或流中收集数据,也可以将
数据立即填充到自定义结构中,毕竟它们已经在单元格中分开了


小心:这只是概念的证明。其中,代码输出如下数据:
System.out.printf(“?%s\n”,…),可能需要一些特定的处理。此外,可能未充分考虑其他边界条件。(实际上,我实现它只是为了正确提取示例PDF的内容。)

不幸的是,您没有共享有问题的PDF,因此我无法判断它是否已标记。你能分享它进行分析吗?@mkl你可以在这里访问示例文件。好啊我会试着调查一下。不过,最有可能在周一之前。(我快速查看了一下。您的PDF已被标记。如果它代表您的源PDF,则提取标记的文本将对您有所帮助。)ExtractMarkedContent已使用当前的PDFBox 3.0.0开发分支快照进行了测试。不过,在当前的2.0.x版本中也应该可以使用。非常感谢您的努力。我将尝试这些方法,看看它们是否能解决我的问题。非常感谢:)。