Java PDFBox 教程展示了如何使用 PDFBox 在 Java 中创建 PDF 文件。
PDFBox
Apache PDFBox 是一个开源 Java 库,可用于创建,渲染,打印,拆分,合并,更改,验证和提取 PDF 文件的文本和元数据。
另一个非常流行的用于处理 PDF 文件的 Java 库称为 iText 。
PDFBox Maven 依赖项
我们需要为我们的项目添加以下 Maven 依赖项。
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.8</version>
</dependency>
Java PDFBox 写文本
在下面的示例中,我们创建一个 PDF 文档并将一些文本写入其中。
JavaPdfBoxWriteText.java
package com.zetcode;
import java.io.IOException;
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 JavaPdfBoxWriteText {
public static void main(String[] args) throws IOException {
try (PDDocument doc = new PDDocument()) {
PDPage myPage = new PDPage();
doc.addPage(myPage);
try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
cont.beginText();
cont.setFont(PDType1Font.TIMES_ROMAN, 12);
cont.setLeading(14.5f);
cont.newLineAtOffset(25, 700);
String line1 = "World War II (often abbreviated to WWII or WW2), "
+ "also known as the Second World War,";
cont.showText(line1);
cont.newLine();
String line2 = "was a global war that lasted from 1939 to 1945, "
+ "although related conflicts began earlier.";
cont.showText(line2);
cont.newLine();
String line3 = "It involved the vast majority of the world's "
+ "countries—including all of the great powers—";
cont.showText(line3);
cont.newLine();
String line4 = "eventually forming two opposing military "
+ "alliances: the Allies and the Axis.";
cont.showText(line4);
cont.newLine();
cont.endText();
}
doc.save("src/main/resources/wwii.pdf");
}
}
}
该示例将四行内容写入 PDF 文档。
try (PDDocument doc = new PDDocument()) {
创建一个新的PDDocument
。 默认情况下,文档具有 A4 格式。
PDPage myPage = new PDPage();
doc.addPage(myPage);
创建一个新页面并将其添加到文档中。
try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
要写入 PDF 页面,我们必须创建一个PDPageContentStream
对象。
cont.beginText();
...
cont.endText();
在beginText()
和endText()
方法之间写入文本。
cont.setFont(PDType1Font.TIMES_ROMAN, 12);
cont.setLeading(14.5f);
我们设置字体和文本开头。
cont.newLineAtOffset(25, 700);
我们使用newLineAtOffset()
方法开始新的一行文本。 页面的原点位于左下角。
String line1 = "World War II (often abbreviated to WWII or WW2), "
+ "also known as the Second World War,";
cont.showText(line1);
文本使用showText()
方法编写。
cont.newLine();
使用newLine()
方法,我们移至下一行文本的开头。
Java PDFBox 读取文本
下一个示例从 PDF 文件读取文本。
JavaPdfBoxReadText.java
package com.zetcode;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
public class JavaPdfBoxReadText {
public static void main(String[] args) throws IOException {
File myFile = new File("src/main/resources/wwii.pdf");
try (PDDocument doc = PDDocument.load(myFile)) {
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(doc);
System.out.println("Text size: " + text.length() + " characters:");
System.out.println(text);
}
}
}
该示例打印 PDF 文档的文本及其大小。
File myFile = new File("src/main/resources/wwii.pdf");
try (PDDocument doc = PDDocument.load(myFile)) {
我们从src/main/resources
目录加载 PDF 文档。
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(doc);
PDFTextStripper
用于从 PDF 文件提取文本。
Java PDFBox 创建图像
下一个示例在 PDF 文档中创建图像。
JavaPdfBoxCreateImage.java
package com.zetcode;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
public class JavaPdfBoxCreateImage {
public static void main(String[] args) throws IOException {
try (PDDocument doc = new PDDocument()) {
PDPage myPage = new PDPage();
doc.addPage(myPage);
String imgFileName = "src/main/resources/sid2.jpg";
PDImageXObject pdImage = PDImageXObject.createFromFile(imgFileName, doc);
int iw = pdImage.getWidth();
int ih = pdImage.getHeight();
float offset = 20f;
try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
cont.drawImage(pdImage, offset, offset, iw, ih);
}
doc.save("src/main/resources/mydoc.pdf");
}
}
}
该示例从目录加载图像,创建新的 PDF 文档,然后将图像添加到页面中。
String imgFileName = "src/main/resources/sid2.jpg";
PDImageXObject pdImage = PDImageXObject.createFromFile(imgFileName, doc);
PDImageXObject
用于处理 PDFBox 中的图像。
int iw = pdImage.getWidth();
int ih = pdImage.getHeight();
我们得到图像的宽度和高度。
try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
cont.drawImage(pdImage, offset, offset, iw, ih);
}
PDPageContentStream's
drawImage()
将图像绘制到页面中。
Java PDFBox 文档信息
PDF 文档可以包含描述文档本身或文档中某些对象(例如文档的作者或创建日期)的信息。 可以使用PDDocumentInformation
对象设置和检索基本信息。
JavaPdfBoxDocumentInformation.java
package com.zetcode;
import java.io.IOException;
import java.util.Calendar;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPage;
public class JavaPdfBoxDocumentInformation {
public static void main(String[] args) throws IOException {
try (PDDocument doc = new PDDocument()) {
PDPage myPage = new PDPage();
doc.addPage(myPage);
PDDocumentInformation pdi = doc.getDocumentInformation();
pdi.setAuthor("Jan Bodnar");
pdi.setTitle("World war II");
pdi.setCreator("Java code");
Calendar date = Calendar.getInstance();
pdi.setCreationDate(date);
pdi.setModificationDate(date);
pdi.setKeywords("World war II, conflict, Allies, Axis powers");
doc.save("src/main/resources/mydoc.pdf");
}
}
}
该示例创建一些文档信息元数据。 该信息可以在 PDF 查看器中的 PDF 文档属性中看到。
PDDocumentInformation pdi = doc.getDocumentInformation();
我们得到PDDocumentInformation
对象。
pdi.setAuthor("Jan Bodnar");
pdi.setTitle("World war II");
pdi.setCreator("Java code");
我们设置一些元数据信息。
Java PDFBox 编写元数据
可扩展元数据平台(XMP)是用于创建,处理和交换数字文档和数据集的标准化和自定义元数据的 ISO 标准。 PDF 文件使用 XMP 来存储其他元数据信息。
metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<rdf:Description rdf:about="">
<dc:title>World war II</dc:title>
<dc:date>2018-01-25</dc:date>
<dc:author>Jan Bodnar</dc:author>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
这是一个 XML 文档,其中包含有关 PDF 文档的一些基本元数据。
JavaPdfBoxMetadataWrite.java
package com.zetcode;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDMetadata;
public class JavaPdfBoxMetadataWrite {
public static void main(String[] args) throws IOException {
try (PDDocument doc = new PDDocument()) {
PDPage myPage = new PDPage();
File myFile = new File("src/main/resources/metadata.xml");
try (InputStream is = Files.newInputStream(myFile.toPath())) {
PDMetadata meta = new PDMetadata(doc, is);
PDDocumentCatalog catalog = doc.getDocumentCatalog();
catalog.setMetadata(meta);
doc.addPage(myPage);
}
doc.save("src/main/resources/mydoc.pdf");
}
}
}
该示例从 XML 文件读取元数据,并将其存储在生成的二进制文档中。
PDMetadata meta = new PDMetadata(doc, is);
PDMetadata
用于处理元数据。
PDDocumentCatalog catalog = doc.getDocumentCatalog();
catalog.setMetadata(meta);
我们将元数据设置为文档的目录。
Java PDFBox 读取元数据
在下一个示例中,我们从 PDF 文档中读取元数据。
JavaPdfBoxMetadataRead.java
package com.zetcode;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.common.PDMetadata;
public class JavaPdfBoxMetadataRead {
public static void main(String[] args) throws IOException {
File myFile = new File("src/main/resources/sinatra.pdf");
try (PDDocument doc = PDDocument.load(myFile)) {
PDDocumentCatalog catalog = doc.getDocumentCatalog();
PDMetadata metadata = catalog.getMetadata();
if (metadata == null) {
System.err.println("No metadata in document");
System.exit(1);
}
try (InputStream is = metadata.createInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
}
}
}
该示例从 PDF 文档读取元数据,并将其打印到控制台。
PDDocumentCatalog catalog = doc.getDocumentCatalog();
PDMetadata metadata = catalog.getMetadata();
我们从PDDocumentCatalog
中检索PDMetadata
。
if (metadata == null) {
System.err.println("No metadata in document");
System.exit(1);
}
该文档可能不包含元数据; 因此,我们进行一些简单的检查。
try (InputStream is = metadata.createInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
createInputStream()
为文档的元数据创建输入流。 我们从该流中读取数据并将其打印到终端。