Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split PDF into separate files based on text

Tags:

split

pdf

I have a large single pdf document which consists of multiple records. Each record usually takes one page however some use 2 pages. A record starts with a defined text, always the same.

My goal is to split this pdf into separate pdfs and the split should happen always before the "header text" is found.

Note: I am looking for a tool or library using java or python. Must be free and available on Win 7.

Any ideas? AFAIK imagemagick won't work for this. May itext do this? I never used and it's pretty complex so would need some hints.

EDIT:

Marked Answer led me to solution. For completeness here my exact implementation:

public void splitByRegex(String filePath, String regex,
        String destinationDirectory, boolean removeBlankPages) throws IOException,
        DocumentException {

    logger.entry(filePath, regex, destinationDirectory);
    destinationDirectory = destinationDirectory == null ? "" : destinationDirectory;
    PdfReader reader = null;
    Document document = null;
    PdfCopy copy = null;
    Pattern pattern = Pattern.compile(regex);        

    try {
        reader = new PdfReader(filePath);
        final String RESULT = destinationDirectory + "/record%d.pdf";
        // loop over all the pages in the original PDF
        int n = reader.getNumberOfPages();
        for (int i = 1; i < n; i++) {

            final String text = PdfTextExtractor.getTextFromPage(reader, i);
            if (pattern.matcher(text).find()) {
                if (document != null && document.isOpen()) {
                    logger.debug("Match found. Closing previous Document..");
                    document.close();
                }
                String fileName = String.format(RESULT, i);
                logger.debug("Match found. Creating new Document " + fileName + "...");
                document = new Document();
                copy = new PdfCopy(document,
                        new FileOutputStream(fileName));
                document.open();
                logger.debug("Adding page to Document...");
                copy.addPage(copy.getImportedPage(reader, i));

            } else if (document != null && document.isOpen()) {
                logger.debug("Found Open Document. Adding additonal page to Document...");
                if (removeBlankPages && !isBlankPage(reader, i)){
                    copy.addPage(copy.getImportedPage(reader, i));
                }
            }
        }
        logger.exit();
    } finally {
        if (document != null && document.isOpen()) {
            document.close();
        }
        if (reader != null) {
            reader.close();
        }
    }
}

private boolean isBlankPage(PdfReader reader, int pageNumber)
        throws IOException {

    // see http://itext-general.2136553.n4.nabble.com/Detecting-blank-pages-td2144877.html
    PdfDictionary pageDict = reader.getPageN(pageNumber);
    // We need to examine the resource dictionary for /Font or
    // /XObject keys.  If either are present, they're almost
    // certainly actually used on the page -> not blank.
    PdfDictionary resDict = (PdfDictionary) pageDict.get(PdfName.RESOURCES);
    if (resDict != null) {
        return resDict.get(PdfName.FONT) == null
                && resDict.get(PdfName.XOBJECT) == null;
    } else {
        return true;
    }
}
like image 379
beginner_ Avatar asked May 03 '13 11:05

beginner_


People also ask

Can you split up a PDF document?

Upload the PDF file you want to split. Click on the scissor icon on the page after which you want to split the document. Click on "Split All" to save all PDF pages individually (optional).

Can I split a PDF without Adobe?

Using Google Chrome. Open the PDF file in Google Chrome. The easiest way to do this is to drag the PDF file into an open Chrome window. You can also right-click on the PDF file, select "Open With", and then select Google Chrome from the list of available programs.


1 Answers

You can create a tool for your requirements using iText.

Whenever you are looking for code samples concerning (current versions of) the iText library, you should consult iText in Action — 2nd Edition the code samples from which are online and searchable by keyword from here.

In your case the relevant samples are Burst.java and ExtractPageContentSorted2.java.

Burst.java shows how to split one PDF in multiple smaller PDFs. The central code:

PdfReader reader = new PdfReader("allrecords.pdf");
final String RESULT = "record%d.pdf";

// We'll create as many new PDFs as there are pages
Document document;
PdfCopy copy;
// loop over all the pages in the original PDF
int n = reader.getNumberOfPages();
for (int i = 0; i < n; ) {
    // step 1
    document = new Document();
    // step 2
    copy = new PdfCopy(document,
            new FileOutputStream(String.format(RESULT, ++i)));
    // step 3
    document.open();
    // step 4
    copy.addPage(copy.getImportedPage(reader, i));
    // step 5
    document.close();
}
reader.close();

This sample splits a PDF in single-page PDFs. In your case you need to split by different criteria. But that only means that in the loop you sometimes have to add more than one imported page (and thus decouple loop index and page numbers to import).

To recognize on which pages a new dataset starts, be inspired by ExtractPageContentSorted2.java. This sample shows how to parse the text content of a page to a string. The central code:

PdfReader reader = new PdfReader("allrecords.pdf");
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
    System.out.println("\nPage " + i);
    System.out.println(PdfTextExtractor.getTextFromPage(reader, i));
}
reader.close();

Simply search for the record start text: If the text from page contains it, a new record starts there.

like image 179
mkl Avatar answered Nov 10 '22 02:11

mkl