Skip to main content

Parse PDF in Java: Extract Text, Tables, Images, and Metadata

 PDFs look straightforward until you need to extract something from them.

A page that appears to contain normal paragraphs and tables may internally be made up of positioned glyphs, embedded images, drawing commands, and metadata objects. As a result, reliable PDF parsing usually requires more than simply “reading the file.”

In a typical Java application, PDF parsing may involve several separate tasks:

  • Loading the document and checking that it can be processed
  • Extracting text page by page
  • Detecting and reading tables
  • Exporting embedded images
  • Reading document metadata

This guide shows how to handle each task with Java. The examples are intentionally separated so that you can use only the parts your project needs or combine them into a larger document-processing pipeline.

java read pdf

1. Install the Required Library

The examples below use Spire.PDF for Java because it provides dedicated APIs for text, table, image, and metadata extraction.

For a Maven project, add the e-iceblue repository and dependency to your pom.xml:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>12.7.0</version>
    </dependency>
</dependencies>

If you are not using Maven, download the JAR package from the official website and add the required files to your project classpath.

Before using the library in a production application, review its licensing terms and choose a version that is compatible with your Java environment.

2. Load a PDF and Check Its Page Count

Before extracting any content, first confirm that the library can open the document and access its page collection.

This is not a complete PDF validation test, but it is a useful early check for unreadable, corrupted, encrypted, or unsupported files.

import com.spire.pdf.PdfDocument;

public class LoadPdf {
    public static void main(String[] args) {
        PdfDocument pdf = new PdfDocument();

        try {
            pdf.loadFromFile("sample.pdf");

            int pageCount = pdf.getPages().getCount();
            System.out.println("Total pages: " + pageCount);
        } finally {
            pdf.close();
        }
    }
}

If the file loads successfully, the application can at least read the document structure and access its page tree.

In a batch-processing system, this step can act as an initial gate. Files that cannot be opened can be logged or moved to a review queue before more expensive extraction operations begin.

For production code, also add exception handling for cases such as:

  • Missing files
  • Password-protected PDFs
  • Unsupported encryption
  • Damaged document structures
  • Permission or file-locking errors

3. Extract Text from Every PDF Page

Text extraction is one of the most common PDF parsing tasks. It is useful for search indexing, document analysis, content migration, summarization, and archiving.

Unlike a plain text file, however, a PDF does not necessarily store text as continuous paragraphs. Individual characters may be placed at specific coordinates on the page. The extraction library must reconstruct the reading order from those positions.

The following example extracts text one page at a time:

import com.spire.pdf.PdfDocument;
import com.spire.pdf.texts.PdfTextExtractOptions;
import com.spire.pdf.texts.PdfTextExtractor;

public class ExtractPdfText {
    public static void main(String[] args) {
        PdfDocument pdf = new PdfDocument();

        try {
            pdf.loadFromFile("sample.pdf");

            StringBuilder extractedText = new StringBuilder();

            PdfTextExtractOptions options = new PdfTextExtractOptions();

            // Produce a simpler reading flow instead of preserving
            // every element's exact visual position.
            options.setSimpleExtraction(true);

            for (int i = 0; i < pdf.getPages().getCount(); i++) {
                PdfTextExtractor extractor =
                        new PdfTextExtractor(pdf.getPages().get(i));

                String pageText = extractor.extract(options);

                extractedText
                        .append("Page ")
                        .append(i + 1)
                        .append(System.lineSeparator())
                        .append(pageText)
                        .append(System.lineSeparator())
                        .append(System.lineSeparator());
            }

            System.out.println(extractedText);
        } finally {
            pdf.close();
        }
    }
}

A few details are worth noting:

  • PdfTextExtractor works on one page at a time.
  • Page-level processing makes it easier to identify pages with extraction problems.
  • setSimpleExtraction(true) can produce a more natural reading flow, although it may flatten some visual layout information.
  • Processing documents page by page can also make large files easier to manage.

The result still depends on how the original PDF was created. Multi-column pages, unusual font encodings, floating text boxes, or heavily positioned content may not be returned in the expected reading order.

Scanned PDFs are a separate case. If a page contains only an image and no selectable text layer, regular text extraction will usually return little or no content. OCR must be applied before or during processing.

4. Extract Tables from a PDF

Tables are common in invoices, financial statements, product catalogs, and operational reports. They are also more difficult to parse than ordinary text.

A PDF does not always store a table as an actual table object. In many documents, the table is simply a collection of text fragments and lines positioned to look like rows and columns.

PdfTableExtractor analyzes the page layout and attempts to reconstruct that structure.

import com.spire.pdf.PdfDocument;
import com.spire.pdf.utilities.PdfTable;
import com.spire.pdf.utilities.PdfTableExtractor;

public class ExtractPdfTables {
    public static void main(String[] args) {
        PdfDocument pdf = new PdfDocument();

        try {
            pdf.loadFromFile("sample.pdf");

            PdfTableExtractor extractor = new PdfTableExtractor(pdf);

            // Extract tables from the first page.
            PdfTable[] tables = extractor.extractTable(0);

            if (tables == null || tables.length == 0) {
                System.out.println("No tables found.");
                return;
            }

            for (int tableIndex = 0; tableIndex < tables.length; tableIndex++) {
                PdfTable table = tables[tableIndex];

                int rowCount = table.getRowCount();
                int columnCount = table.getColumnCount();

                System.out.println(
                        "Table " + (tableIndex + 1)
                                + ": " + rowCount + " rows, "
                                + columnCount + " columns"
                );

                StringBuilder output = new StringBuilder();

                for (int row = 0; row < rowCount; row++) {
                    for (int column = 0; column < columnCount; column++) {
                        String cellText = table.getText(row, column);

                        if (cellText != null) {
                            cellText = cellText
                                    .replace("\r", " ")
                                    .replace("\n", " ")
                                    .trim();
                        }

                        output.append(cellText == null ? "" : cellText);

                        if (column < columnCount - 1) {
                            output.append('\t');
                        }
                    }

                    output.append(System.lineSeparator());
                }

                System.out.println(output);
            }
        } finally {
            pdf.close();
        }
    }
}

This example prints the extracted cells as tab-separated values. In a real application, you might instead:

  • Export the data to CSV
  • Convert it to JSON
  • Insert it into a database
  • Map rows to Java objects
  • Send it to an analytics pipeline

Table extraction works best when the source document has regular rows, consistent columns, and clear spacing or borders.

Results may require cleanup when a table contains:

  • Merged cells
  • Nested tables
  • Multi-line headers
  • Irregular column widths
  • Missing borders
  • Text that overlaps cell boundaries

Header rows are not always identified automatically. If your application needs to distinguish headers from data rows, add validation or document-specific rules after extraction.

5. Export Images Embedded in PDF Pages

Image extraction can be useful for archiving, auditing, document migration, or separating visual assets from the surrounding text.

The following example finds raster images on each page and saves them as PNG files:

import com.spire.pdf.PdfDocument;
import com.spire.pdf.utilities.PdfImageHelper;
import com.spire.pdf.utilities.PdfImageInfo;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ExtractPdfImages {
    public static void main(String[] args) throws IOException {
        PdfDocument pdf = new PdfDocument();

        try {
            pdf.loadFromFile("sample.pdf");

            File outputDirectory = new File("images");

            if (!outputDirectory.exists() && !outputDirectory.mkdirs()) {
                throw new IOException(
                        "Could not create output directory: "
                                + outputDirectory.getAbsolutePath()
                );
            }

            PdfImageHelper imageHelper = new PdfImageHelper();

            for (int pageIndex = 0;
                 pageIndex < pdf.getPages().getCount();
                 pageIndex++) {

                PdfImageInfo[] imageInfo =
                        imageHelper.getImagesInfo(
                                pdf.getPages().get(pageIndex)
                        );

                if (imageInfo == null || imageInfo.length == 0) {
                    continue;
                }

                for (int imageIndex = 0;
                     imageIndex < imageInfo.length;
                     imageIndex++) {

                    BufferedImage image =
                            imageInfo[imageIndex].getImage();

                    File outputFile = new File(
                            outputDirectory,
                            "page_" + (pageIndex + 1)
                                    + "_image_" + (imageIndex + 1)
                                    + ".png"
                    );

                    ImageIO.write(image, "PNG", outputFile);

                    System.out.println(
                            "Saved: " + outputFile.getPath()
                    );
                }
            }
        } finally {
            pdf.close();
        }
    }
}

A few practical limitations apply:

  • Logos, backgrounds, and decorative graphics may also be returned.
  • Very large images can consume significant memory.
  • The extracted color space or compression may differ from the original asset.
  • Vector drawings are not necessarily returned as raster images.
  • A single visual illustration may be composed of several separate resources.

If you only need certain images, consider filtering the results by dimensions, file size, page location, or other available metadata.

For large batch jobs, process one page at a time and avoid keeping unnecessary BufferedImage instances in memory.

6. Read PDF Metadata

PDF metadata may include the document title, author, subject, keywords, creator application, producer, and creation or modification dates.

Reading this information is inexpensive because it does not require iterating through every page.

import com.spire.pdf.PdfDocument;

public class ReadPdfMetadata {
    public static void main(String[] args) {
        PdfDocument pdf = new PdfDocument();

        try {
            pdf.loadFromFile("sample.pdf");

            System.out.println(
                    "Title: "
                            + pdf.getDocumentInformation().getTitle()
            );
            System.out.println(
                    "Author: "
                            + pdf.getDocumentInformation().getAuthor()
            );
            System.out.println(
                    "Subject: "
                            + pdf.getDocumentInformation().getSubject()
            );
            System.out.println(
                    "Keywords: "
                            + pdf.getDocumentInformation().getKeywords()
            );
            System.out.println(
                    "Creator: "
                            + pdf.getDocumentInformation().getCreator()
            );
            System.out.println(
                    "Producer: "
                            + pdf.getDocumentInformation().getProducer()
            );
            System.out.println(
                    "Creation date: "
                            + pdf.getDocumentInformation().getCreationDate()
            );
            System.out.println(
                    "Modification date: "
                            + pdf.getDocumentInformation().getModificationDate()
            );
        } finally {
            pdf.close();
        }
    }
}

Do not assume that metadata is complete or trustworthy.

Some documents contain no metadata, while others contain outdated or automatically generated values. A PDF may also claim an author or creation date that does not reflect the actual source of the document.

Treat metadata as a useful classification signal rather than definitive proof about a file's origin.

In a document-processing system, metadata can help with:

  • Routing documents to different workflows
  • Building search indexes
  • Applying naming conventions
  • Detecting likely duplicates
  • Organizing files by author or date

Always handle missing values before storing or displaying them.

7. Build a Maintainable Parsing Pipeline

In a real application, these operations are usually more useful when combined into a pipeline.

A typical workflow might look like this:

  1. Verify that the file exists and can be opened.
  2. Read metadata for classification or routing.
  3. Determine whether the PDF has a usable text layer.
  4. Extract text page by page.
  5. Detect and export tables where needed.
  6. Export relevant images.
  7. Store the results in a database, search index, or file system.
  8. Send failed or low-confidence documents for review.

Keeping these stages separate has several advantages. A failure during table extraction does not have to prevent metadata or text extraction, and each stage can be tested, logged, or replaced independently.

A simple domain model might store the result like this:

public class ParsedPdf {
    private String title;
    private String author;
    private String text;
    private int pageCount;

    // Add table, image, error, and page-level result fields as needed.
}

For larger systems, consider keeping page-level results instead of combining the entire document into one large string. That makes it easier to:

  • Trace extracted content back to a page
  • Retry only failed pages
  • Build page-aware search results
  • Process documents in parallel
  • Limit memory usage

Common PDF Parsing Limitations

Even with a dedicated library, PDF parsing is not always predictable.

Scanned or image-only PDFs

If the PDF has no selectable text layer, regular text and table extraction will not work reliably. Use OCR, such as Tesseract or another OCR service, before applying text-based parsing.

Complex page layouts

Multiple columns, floating elements, borderless tables, merged cells, and irregular spacing can affect reading order and table detection.

For highly structured document types, a document-specific parser may produce better results than a completely generic pipeline.

Font encoding issues

Some PDFs use custom font encodings or incomplete character maps. This can result in missing characters, incorrect symbols, or unreadable output.

Trying different text extraction settings may help, but some files will still require OCR or manual correction.

Memory usage

Large PDFs and high-resolution images can use substantial memory. Process documents page by page, release references as soon as possible, and avoid loading unnecessary image data.

Error handling

A production parser should expect individual files or pages to fail. Log enough context to identify the source file, page number, and failed operation without stopping an entire batch unnecessarily.

Resource cleanup

Always call pdf.close() after processing. This releases file handles and native resources, which is especially important when processing many files in a long-running service.

Comments

Popular posts from this blog

3 Ways to Generate Word Documents from Templates in Java

A template is a document with pre-applied formatting like styles, tabs, line spacing and so on. You can quickly generate a batch of documents with the same structure based on the template. In this article, I am going to show you the different ways to generate Word documents from templates programmatically in Java using Free Spire.Doc for Java library. Prerequisite First of all, you need to add needed dependencies for including Free Spire.Doc for Java into your Java project. There are two ways to do that. If you use maven, you need to add the following code to your project’s pom.xml file. <repositories>               <repository>                   <id>com.e-iceblue</id>                   <name>e-iceblue</name>...

Insert and Extract OLE objects in Word in Java

You can use OLE (Object Linking and Embedding) to include content from other programs, such as another Word document, an Excel or PowerPoint document to an existing Word document. This article demonstrates how to insert and extract embedded OLE objects in a Word document in Java by using Free Spire.Doc for Java API.   Add dependencies First of all, you need to add needed dependencies for including Free Spire.Doc for Java into your Java project. There are two ways to do that. If you use maven, you need to add the following code to your project’s pom.xml file.     <repositories>               <repository>                   <id>com.e-iceblue</id>                   <name>e-iceblue</name>    ...

Simple Java Code to Convert Excel to PDF in Java

This article demonstrates a simple solution to convert an Excel file to PDF in Java by using free Excel API – Free Spire.XLS for Java . The following examples illustrate two possibilities to convert Excel to PDF:      Convert the whole Excel file to PDF     Convert a particular Excel Worksheet to PDF Before start with coding, you need to Download Free Spire.XLS for Java package , unzip it and import Spire.Xls.jar file from the lib folder in your project as a denpendency. 1. Convert the whole Excel file to PDF Spire.XLS for Java provides saveToFile method in Workbook class that enables us to easily save a whole Excel file to PDF. import com.spire.xls.FileFormat; import com.spire.xls.Workbook; public class ExcelToPDF {     public static void main(String[] args){         //Create a Workbook         Workbook workbook = new Workbook();   ...