如何使用Java PDFBox根据结果拆分PDF文件

4

我有一个包含60页的PDF文件,每一页都有独特和重复的发票号码。我正在使用Apache PDFBOX。

import java.io.*;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.util.*;
import java.util.regex.*;

public class PDFtest1 {
public static void main(String[] args){
PDDocument pd;
try {

     File input = new File("G:\\Sales.pdf");

     // StringBuilder to store the extracted text
     StringBuilder sb = new StringBuilder();
     pd = PDDocument.load(input);
     PDFTextStripper stripper = new PDFTextStripper();

     // Add text to the StringBuilder from the PDF
     sb.append(stripper.getText(pd));


     Pattern p = Pattern.compile("Invoice No.\\s\\w\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d");

     // Matcher refers to the actual text where the pattern will be found
     Matcher m = p.matcher(sb);

     while (m.find()){
         // group() method refers to the next number that follows the pattern we have specified.
         System.out.println(m.group());
     }

     if (pd != null) {
         pd.close();
     }
   } catch (Exception e){
     e.printStackTrace();
    }
 }
 }  

我能使用Java正则表达式来读取所有发票编号。最终结果如下:
run:
Invoice No. D0000003010
Invoice No. D0000003011
Invoice No. D0000003011
Invoice No. D0000003011
Invoice No. D0000003011
Invoice No. D0000003012
Invoice No. D0000003012
Invoice No. D0000003012
Invoice No. D0000003013
Invoice No. D0000003013
Invoice No. D0000003014
Invoice No. D0000003014
Invoice No. D0000003015
Invoice No. D0000003016

我需要根据发票号码拆分PDF文件。例如,对于发票号码D0000003011,所有PDF页面应合并为单个PDF文件,以此类推。我该如何实现这一点?

相同的发票号码是否总是在一起?您使用的PDFBox版本是什么? - Tilman Hausherr
是的,在某些页面中,发票号是唯一的,而在某些页面中会重复出现相同的值,即副本。我正在使用PDFBox 0.7.3.jar文件,并且还使用PDFBox-app-1.8.10.jar文件。 - User9999
1个回答

6
public static void main(String[] args) throws IOException, COSVisitorException
{
    File input = new File("G:\\Sales.pdf");

    PDDocument outputDocument = null;
    PDDocument inputDocument = PDDocument.loadNonSeq(input, null);
    PDFTextStripper stripper = new PDFTextStripper();
    String currentNo = null;
    for (int page = 1; page <= inputDocument.getNumberOfPages(); ++page)
    {
        stripper.setStartPage(page);
        stripper.setEndPage(page);
        String text = stripper.getText(inputDocument);
        Pattern p = Pattern.compile("Invoice No.(\\s\\w\\d\\d\\d\\d\\d\\d\\d\\d\\d\\d)");

        // Matcher refers to the actual text where the pattern will be found
        Matcher m = p.matcher(text);
        String no = null;
        if (m.find())
        {
            no = m.group(1);
        }
        System.out.println("page: " + page + ", value: " + no);

        PDPage pdPage = (PDPage) inputDocument.getDocumentCatalog().getAllPages().get(page - 1);

        if (no != null && !no.equals(currentNo))
        {
            saveCloseCurrent(currentNo, outputDocument);
            // create new document
            outputDocument = new PDDocument();
            currentNo = no;
        }
        if (no == null && currentNo == null)
        {
            System.out.println ("header page ??? " + page + " skipped");
            continue;
        }
        // append page to current document
        outputDocument.importPage(pdPage);
    }
    saveCloseCurrent(currentNo, outputDocument);
    inputDocument.close();
}

private static void saveCloseCurrent(String currentNo, PDDocument outputDocument)
        throws IOException, COSVisitorException
{
    // save to new output file
    if (currentNo != null)
    {
        // save document into file
        File f = new File(currentNo + ".pdf");
        if (f.exists())
        {
            System.err.println("File " + f + " exists?!");
            System.exit(-1);
        }
        outputDocument.save(f);
        outputDocument.close();
    }
}

注意:

  • 这个代码没有经过你的文件测试(因为我没有它);
  • 代码假定相同的发票编号总是在一起;
  • 你的正则表达式已经稍作修改;
  • 确保第一个和最后一个PDF文件是正确的,并随机检查一些文件,如果有不同的查看器,请使用不同的查看器;
  • 验证文件总数是否符合预期;
  • 所有文件的总大小将比源文件大,这是由于字体资源的原因;
  • 使用1.8.10版本。不要同时使用PDFBox 0.7.3.jar!
  • 错误处理非常基础,你需要改变它;

更新于2015年8月19日:

  • 现在它支持没有发票编号的页面,这些页面将会被追加。

1
@KiranP,如果要跳过空页面,请将“nothing found on page”段落替换为“continue;”,例如以下代码:if (!m.find()) { continue; }或者有这样一个要求,即某些页面没有发票号,但仍必须附加。 - Tilman Hausherr
@KiranP 的代码已经得到改进,希望能有所帮助。请学会非常精确地表达,例如当你真正想表达“源PDF的第二页没有发票号码”时,请不要写成“第二个PDF为空”。 - Tilman Hausherr
@KiranP,我发现有个 bug,我又改进了代码。请看看现在是否可以工作了。 - Tilman Hausherr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接