原文:http://zetcode.com/java/pdfbox/

Java PDFBox 教程展示了如何使用 PDFBox 在 Java 中创建 PDF 文件。

PDFBox

Apache PDFBox 是一个开源 Java 库,可用于创建,渲染,打印,拆分,合并,更改,验证和提取 PDF 文件的文本和元数据。

另一个非常流行的用于处理 PDF 文件的 Java 库称为 iText 。

PDFBox Maven 依赖项

我们需要为我们的项目添加以下 Maven 依赖项。

  1. <dependency>
  2. <groupId>org.apache.pdfbox</groupId>
  3. <artifactId>pdfbox</artifactId>
  4. <version>2.0.8</version>
  5. </dependency>

Java PDFBox 写文本

在下面的示例中,我们创建一个 PDF 文档并将一些文本写入其中。

JavaPdfBoxWriteText.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import org.apache.pdfbox.pdmodel.PDDocument;
  4. import org.apache.pdfbox.pdmodel.PDPage;
  5. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  6. import org.apache.pdfbox.pdmodel.font.PDType1Font;
  7. public class JavaPdfBoxWriteText {
  8. public static void main(String[] args) throws IOException {
  9. try (PDDocument doc = new PDDocument()) {
  10. PDPage myPage = new PDPage();
  11. doc.addPage(myPage);
  12. try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
  13. cont.beginText();
  14. cont.setFont(PDType1Font.TIMES_ROMAN, 12);
  15. cont.setLeading(14.5f);
  16. cont.newLineAtOffset(25, 700);
  17. String line1 = "World War II (often abbreviated to WWII or WW2), "
  18. + "also known as the Second World War,";
  19. cont.showText(line1);
  20. cont.newLine();
  21. String line2 = "was a global war that lasted from 1939 to 1945, "
  22. + "although related conflicts began earlier.";
  23. cont.showText(line2);
  24. cont.newLine();
  25. String line3 = "It involved the vast majority of the world's "
  26. + "countries—including all of the great powers—";
  27. cont.showText(line3);
  28. cont.newLine();
  29. String line4 = "eventually forming two opposing military "
  30. + "alliances: the Allies and the Axis.";
  31. cont.showText(line4);
  32. cont.newLine();
  33. cont.endText();
  34. }
  35. doc.save("src/main/resources/wwii.pdf");
  36. }
  37. }
  38. }

该示例将四行内容写入 PDF 文档。

  1. try (PDDocument doc = new PDDocument()) {

创建一个新的PDDocument。 默认情况下,文档具有 A4 格式。

  1. PDPage myPage = new PDPage();
  2. doc.addPage(myPage);

创建一个新页面并将其添加到文档中。

  1. try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {

要写入 PDF 页面,我们必须创建一个PDPageContentStream对象。

  1. cont.beginText();
  2. ...
  3. cont.endText();

beginText()endText()方法之间写入文本。

  1. cont.setFont(PDType1Font.TIMES_ROMAN, 12);
  2. cont.setLeading(14.5f);

我们设置字体和文本开头。

  1. cont.newLineAtOffset(25, 700);

我们使用newLineAtOffset()方法开始新的一行文本。 页面的原点位于左下角。

  1. String line1 = "World War II (often abbreviated to WWII or WW2), "
  2. + "also known as the Second World War,";
  3. cont.showText(line1);

文本使用showText()方法编写。

  1. cont.newLine();

使用newLine()方法,我们移至下一行文本的开头。

Java PDFBox 读取文本

下一个示例从 PDF 文件读取文本。

JavaPdfBoxReadText.java

  1. package com.zetcode;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import org.apache.pdfbox.pdmodel.PDDocument;
  5. import org.apache.pdfbox.text.PDFTextStripper;
  6. public class JavaPdfBoxReadText {
  7. public static void main(String[] args) throws IOException {
  8. File myFile = new File("src/main/resources/wwii.pdf");
  9. try (PDDocument doc = PDDocument.load(myFile)) {
  10. PDFTextStripper stripper = new PDFTextStripper();
  11. String text = stripper.getText(doc);
  12. System.out.println("Text size: " + text.length() + " characters:");
  13. System.out.println(text);
  14. }
  15. }
  16. }

该示例打印 PDF 文档的文本及其大小。

  1. File myFile = new File("src/main/resources/wwii.pdf");
  2. try (PDDocument doc = PDDocument.load(myFile)) {

我们从src/main/resources目录加载 PDF 文档。

  1. PDFTextStripper stripper = new PDFTextStripper();
  2. String text = stripper.getText(doc);

PDFTextStripper用于从 PDF 文件提取文本。

Java PDFBox 创建图像

下一个示例在 PDF 文档中创建图像。

JavaPdfBoxCreateImage.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import org.apache.pdfbox.pdmodel.PDDocument;
  4. import org.apache.pdfbox.pdmodel.PDPage;
  5. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  6. import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
  7. public class JavaPdfBoxCreateImage {
  8. public static void main(String[] args) throws IOException {
  9. try (PDDocument doc = new PDDocument()) {
  10. PDPage myPage = new PDPage();
  11. doc.addPage(myPage);
  12. String imgFileName = "src/main/resources/sid2.jpg";
  13. PDImageXObject pdImage = PDImageXObject.createFromFile(imgFileName, doc);
  14. int iw = pdImage.getWidth();
  15. int ih = pdImage.getHeight();
  16. float offset = 20f;
  17. try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
  18. cont.drawImage(pdImage, offset, offset, iw, ih);
  19. }
  20. doc.save("src/main/resources/mydoc.pdf");
  21. }
  22. }
  23. }

该示例从目录加载图像,创建新的 PDF 文档,然后将图像添加到页面中。

  1. String imgFileName = "src/main/resources/sid2.jpg";
  2. PDImageXObject pdImage = PDImageXObject.createFromFile(imgFileName, doc);

PDImageXObject用于处理 PDFBox 中的图像。

  1. int iw = pdImage.getWidth();
  2. int ih = pdImage.getHeight();

我们得到图像的宽度和高度。

  1. try (PDPageContentStream cont = new PDPageContentStream(doc, myPage)) {
  2. cont.drawImage(pdImage, offset, offset, iw, ih);
  3. }

PDPageContentStreamdrawImage()将图像绘制到页面中。

Java PDFBox 文档信息

PDF 文档可以包含描述文档本身或文档中某些对象(例如文档的作者或创建日期)的信息。 可以使用PDDocumentInformation对象设置和检索基本信息。

JavaPdfBoxDocumentInformation.java

  1. package com.zetcode;
  2. import java.io.IOException;
  3. import java.util.Calendar;
  4. import org.apache.pdfbox.pdmodel.PDDocument;
  5. import org.apache.pdfbox.pdmodel.PDDocumentInformation;
  6. import org.apache.pdfbox.pdmodel.PDPage;
  7. public class JavaPdfBoxDocumentInformation {
  8. public static void main(String[] args) throws IOException {
  9. try (PDDocument doc = new PDDocument()) {
  10. PDPage myPage = new PDPage();
  11. doc.addPage(myPage);
  12. PDDocumentInformation pdi = doc.getDocumentInformation();
  13. pdi.setAuthor("Jan Bodnar");
  14. pdi.setTitle("World war II");
  15. pdi.setCreator("Java code");
  16. Calendar date = Calendar.getInstance();
  17. pdi.setCreationDate(date);
  18. pdi.setModificationDate(date);
  19. pdi.setKeywords("World war II, conflict, Allies, Axis powers");
  20. doc.save("src/main/resources/mydoc.pdf");
  21. }
  22. }
  23. }

该示例创建一些文档信息元数据。 该信息可以在 PDF 查看器中的 PDF 文档属性中看到。

  1. PDDocumentInformation pdi = doc.getDocumentInformation();

我们得到PDDocumentInformation对象。

  1. pdi.setAuthor("Jan Bodnar");
  2. pdi.setTitle("World war II");
  3. pdi.setCreator("Java code");

我们设置一些元数据信息。

Java PDFBox 编写元数据

可扩展元数据平台(XMP)是用于创建,处理和交换数字文档和数据集的标准化和自定义元数据的 ISO 标准。 PDF 文件使用 XMP 来存储其他元数据信息。

metadata.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <x:xmpmeta xmlns:x="adobe:ns:meta/">
  3. <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  4. xmlns:foaf="http://xmlns.com/foaf/0.1/"
  5. xmlns:dc="http://purl.org/dc/elements/1.1/">
  6. <rdf:Description rdf:about="">
  7. <dc:title>World war II</dc:title>
  8. <dc:date>2018-01-25</dc:date>
  9. <dc:author>Jan Bodnar</dc:author>
  10. </rdf:Description>
  11. </rdf:RDF>
  12. </x:xmpmeta>

这是一个 XML 文档,其中包含有关 PDF 文档的一些基本元数据。

JavaPdfBoxMetadataWrite.java

  1. package com.zetcode;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.nio.file.Files;
  6. import org.apache.pdfbox.pdmodel.PDDocument;
  7. import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
  8. import org.apache.pdfbox.pdmodel.PDPage;
  9. import org.apache.pdfbox.pdmodel.common.PDMetadata;
  10. public class JavaPdfBoxMetadataWrite {
  11. public static void main(String[] args) throws IOException {
  12. try (PDDocument doc = new PDDocument()) {
  13. PDPage myPage = new PDPage();
  14. File myFile = new File("src/main/resources/metadata.xml");
  15. try (InputStream is = Files.newInputStream(myFile.toPath())) {
  16. PDMetadata meta = new PDMetadata(doc, is);
  17. PDDocumentCatalog catalog = doc.getDocumentCatalog();
  18. catalog.setMetadata(meta);
  19. doc.addPage(myPage);
  20. }
  21. doc.save("src/main/resources/mydoc.pdf");
  22. }
  23. }
  24. }

该示例从 XML 文件读取元数据,并将其存储在生成的二进制文档中。

  1. PDMetadata meta = new PDMetadata(doc, is);

PDMetadata用于处理元数据。

  1. PDDocumentCatalog catalog = doc.getDocumentCatalog();
  2. catalog.setMetadata(meta);

我们将元数据设置为文档的目录。

Java PDFBox 读取元数据

在下一个示例中,我们从 PDF 文档中读取元数据。

JavaPdfBoxMetadataRead.java

  1. package com.zetcode;
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. import org.apache.pdfbox.pdmodel.PDDocument;
  8. import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
  9. import org.apache.pdfbox.pdmodel.common.PDMetadata;
  10. public class JavaPdfBoxMetadataRead {
  11. public static void main(String[] args) throws IOException {
  12. File myFile = new File("src/main/resources/sinatra.pdf");
  13. try (PDDocument doc = PDDocument.load(myFile)) {
  14. PDDocumentCatalog catalog = doc.getDocumentCatalog();
  15. PDMetadata metadata = catalog.getMetadata();
  16. if (metadata == null) {
  17. System.err.println("No metadata in document");
  18. System.exit(1);
  19. }
  20. try (InputStream is = metadata.createInputStream();
  21. InputStreamReader isr = new InputStreamReader(is);
  22. BufferedReader br = new BufferedReader(isr)) {
  23. br.lines().forEach(System.out::println);
  24. }
  25. }
  26. }
  27. }

该示例从 PDF 文档读取元数据,并将其打印到控制台。

  1. PDDocumentCatalog catalog = doc.getDocumentCatalog();
  2. PDMetadata metadata = catalog.getMetadata();

我们从PDDocumentCatalog中检索PDMetadata

  1. if (metadata == null) {
  2. System.err.println("No metadata in document");
  3. System.exit(1);
  4. }

该文档可能不包含元数据; 因此,我们进行一些简单的检查。

  1. try (InputStream is = metadata.createInputStream();
  2. InputStreamReader isr = new InputStreamReader(is);
  3. BufferedReader br = new BufferedReader(isr)) {
  4. br.lines().forEach(System.out::println);
  5. }

createInputStream()为文档的元数据创建输入流。 我们从该流中读取数据并将其打印到终端。

在本教程中,我们展示了如何使用 PDFBox 库在 Java 中使用 PDF 文件。 您可能也对相关教程感兴趣: Java JFreeChart 教程Java 2D 教程Java 教程