Why More Developers Choose Apache PDFBox for PDF Processing
This article provides a comprehensive guide to Apache PDFBox, covering its licensing advantages, architecture, installation, core operations such as creating, editing, extracting, merging, encrypting PDFs, migration tips from 2.x to 3.x, performance considerations, and recommended use cases for Java backend development.
What is PDFBox?
Apache PDFBox is an open‑source Java library for processing PDF documents. It can create new PDFs, edit existing PDFs, extract text, images and metadata, and merge, split, encrypt, decrypt and sign PDFs.
Environment setup (≈5 minutes)
Add the dependency
PDFBox 3.x requires Java 8+. Maven:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.8</version>
</dependency>Gradle:
implementation 'org.apache.pdfbox:pdfbox:3.0.8'First program – extract text
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import java.io.File;
import java.io.IOException;
public class ExtractText {
public static void main(String[] args) throws IOException {
File file = new File("sample.pdf");
try (PDDocument document = Loader.loadPDF(file)) {
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(document);
System.out.println(text);
}
}
}Note: PDFBox 3.0 removed PDDocument.load(); use Loader.loadPDF() instead.
Extract a page range
try (PDDocument document = Loader.loadPDF(new File("sample.pdf"))) {
PDFTextStripper stripper = new PDFTextStripper();
stripper.setStartPage(2); // start from page 2
stripper.setEndPage(4); // end at page 4
String text = stripper.getText(document);
System.out.println(text);
}Core operations
Create a PDF document
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
public class CreatePDF {
public static void main(String[] args) {
try (PDDocument document = new PDDocument()) {
PDPage page = new PDPage();
document.addPage(page);
PDPageContentStream cs = new PDPageContentStream(document, page);
cs.setFont(PDType1Font.HELVETICA_BOLD, 12);
cs.beginText();
cs.newLineAtOffset(100, 700); // X=100, Y=700 from lower‑left corner
cs.showText("Hello, PDFBox!");
cs.endText();
cs.close();
document.save("HelloPDFBox.pdf");
} catch (Exception e) {
e.printStackTrace();
}
}
}The coordinate origin is the lower‑left corner; X increases to the right, Y upward.
Multi‑line text handling:
contentStream.setLeading(14.5f); // line spacing
contentStream.showText("First line");
contentStream.newLine();
contentStream.showText("Second line");Extract images
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.cos.COSName;
import java.io.File;
import java.io.IOException;
public class ExtractImages {
public static void main(String[] args) throws IOException {
try (PDDocument document = Loader.loadPDF(new File("sample.pdf"))) {
for (int i = 0; i < document.getNumberOfPages(); i++) {
PDPage page = document.getPage(i);
PDResources res = page.getResources();
for (COSName name : res.getXObjectNames()) {
if (res.isImageXObject(name)) {
PDImageXObject img = (PDImageXObject) res.getXObject(name);
System.out.println("Found image: " + name.getName());
// img.getImage() returns a BufferedImage you can save
}
}
}
}
}
}Merge PDFs
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import java.io.File;
import java.io.IOException;
public class MergePDFs {
public static void main(String[] args) throws IOException {
PDFMergerUtility merger = new PDFMergerUtility();
merger.addSource(new File("file1.pdf"));
merger.addSource(new File("file2.pdf"));
merger.addSource(new File("file3.pdf"));
merger.setDestinationFileName("merged.pdf");
merger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
}
}Encrypt PDFs
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
import java.io.File;
import java.io.IOException;
public class EncryptPDF {
public static void main(String[] args) throws IOException {
try (PDDocument document = Loader.loadPDF(new File("sample.pdf"))) {
AccessPermission ap = new AccessPermission();
ap.setCanPrint(true); // allow printing
ap.setCanModify(false); // disallow modification
StandardProtectionPolicy spp = new StandardProtectionPolicy(
"user_password", // user password
"owner_password", // owner password
ap);
spp.setEncryptionKeyLength(128);
document.protect(spp);
document.save("encrypted.pdf");
}
}
}Fill PDF forms
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
import java.io.File;
import java.io.IOException;
public class FillForm {
public static void main(String[] args) throws IOException {
try (PDDocument document = Loader.loadPDF(new File("form.pdf"))) {
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
PDTextField nameField = (PDTextField) acroForm.getField("name");
if (nameField != null) {
nameField.setValue("Zhang San");
}
PDTextField emailField = (PDTextField) acroForm.getField("email");
if (emailField != null) {
emailField.setValue("[email protected]");
}
document.save("filled_form.pdf");
}
}
}Underlying architecture
How does PDFBox turn a binary PDF file into readable text and images?
Physical structure of a PDF
Header – version information (e.g. %PDF-1.7)
Body – objects such as pages, images, fonts, annotations
Cross‑reference table – enables fast object location
Trailer – points to the cross‑reference table and the document root
PDFBox two‑layer architecture
PDFBox separates low‑level PDF objects (COS layer) from high‑level APIs (PD layer).
COS layer maps directly to PDF objects such as COSDictionary, COSArray, COSStream. The PD layer provides developer‑friendly classes like PDDocument, PDPage, PDPageContentStream. This design lets you start with the PD layer for common tasks and drop down to the COS layer when full control is needed.
Three processing layers:
Base layer ( PDFStreamEngine) – parses content streams into tokens.
Graphics abstraction layer ( PDFGraphicsStreamEngine) – defines drawing operations.
Implementation layer ( PageDrawer, PDFTextStripper) – concrete rendering and text extraction.
For text extraction, PDFTextStripper overrides showGlyph() to collect character positions.
The architecture is highly extensible; you can subclass PDFStreamEngine to implement custom analysis or rendering.
Common issues and pitfalls
Migration from 2.x to 3.x
PDDocument.load()removed – use Loader.loadPDF().
IO module refactored – new Loader class introduced.
Chinese text support
Default PDType1Font does not support Chinese. Load a TrueType font manually:
PDType0Font font = PDType0Font.load(document, new File("simsun.ttf"));
contentStream.setFont(font, 12);Large‑file performance
Use Loader.loadPDF() with a MemoryUsageSetting to control memory consumption.
Process very large files page‑by‑page.
Employ try‑with‑resources to ensure timely release of resources.
Pros and cons
Advantages
Apache 2.0 license – commercial‑friendly.
All‑in‑one feature set (create, edit, extract, sign, merge, etc.).
Active Apache top‑level project with frequent releases.
Intuitive API – easy for newcomers.
Command‑line tools for quick tasks.
Pure Java implementation – runs anywhere Java runs.
Disadvantages
Performance on very large or complex PDFs can be slower than commercial libraries.
Table extraction is not built‑in; external tools like Tabula‑java are needed.
Chinese characters require manual font loading.
Version 3.0 introduces breaking API changes.
Recommended scenarios
Document management systems – strong recommendation (create, edit, extract).
Automated report generation – strong recommendation (generate complex PDFs with charts and tables).
Invoice/contract parsing – strong recommendation (extract structured data under a commercial‑friendly license).
E‑book readers – recommended (text search and content extraction).
Digital signatures – recommended (PDF‑standard signing).
PDF merge/split – recommended (use PDFMergerUtility).
Final thoughts
Apache PDFBox, as an Apache top‑level project under the Apache 2.0 license, gives developers maximum freedom to use, modify and ship the library even in closed‑source commercial products. It covers creation, editing, extraction, encryption, signing and merging with a straightforward API.
Performance on massive files and native table extraction are its main limitations, but for most PDF processing needs PDFBox is more than sufficient.
Source code repository: https://github.com/apache/pdfbox
Official documentation: https://pdfbox.apache.org
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
SpringMeng
Focused on software development, sharing source code and tutorials for various systems.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
