当前位置: 首页 > news >正文

使用 Apache PDFBox 操作PDF文件

简介

Apache PDFBox库是一个开源的Java工具,专门用于处理PDF文档。它允许用户创建全新的PDF文件,编辑现有的PDF文档,以及从PDF文件中提取内容。此外,Apache PDFBox还提供了一些命令行实用工具。

Apache PDFBox提供了创建、渲染、打印、合并、拆分、加密、解密、签名等多种操作PDF文件的功能。PDFBox还包括一个命令行工具,可以用于执行各种PDF处理任务。此外,它还支持文本提取和搜索,以及将PDF转换为其他格式,如图片和文本。PDFBox广泛应用于企业和开发者构建PDF处理相关的应用程序和工具。

Apache PDFBox具备以下主要功能:

  • 从PDF文件中提取Unicode文本。
  • 将单个PDF文件拆分成多个文件,或将多个PDF文件合并成一个。
  • 从PDF表单中提取数据,或填写PDF表单。
  • 验证PDF文件是否符合PDF/A-1b标准。
  • 使用标准的Java打印API打印PDF文件。
  • 将PDF文件另存为图像格式,如PNG或JPEG。
  • 从零开始创建PDF文件,包括嵌入字体和图像。
  • 对PDF文件进行数字签名。

导入

首先,我们需要确保已经将PDFBox库添加到我的Java项目中。如果你使用的是maven,那么在pom.xml中添加如下依赖:

<dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.28</version>
</dependency>

这里使用的版本是:2.0.28。

Talk is cheap. Show me the code.

接下来,我们将通过代码示例展示如何使用Apache PDFBox来创建PDF文档、读取PDF文件、插入图片以及读取图片。

创建PDF文档

我们可以使用以下代码创建一个简单的PDF文档:

import java.io.File;
import java.io.IOException;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.font.PDType1Font;public class CreatePDF {public static void main(String[] args) {PDDocument document = new PDDocument();PDPage page = new PDPage();document.addPage(page);PDType1Font font = PDType1Font.HELVETICA_BOLD;try {PDPageContentStream contentStream = new PDPageContentStream(document, page);contentStream.beginText();contentStream.setFont(font, 12);contentStream.newLineAtOffset(100, 700);contentStream.showText("Hello, World!");contentStream.endText();contentStream.close();document.save(new File("one-more.pdf"));document.close();System.out.println("PDF created successfully.");} catch (IOException e) {e.printStackTrace();}}
}

这个代码段创建一个新的PDF文档,并在其第一页上写入"Hello, World!"。我使用了Helvetica Bold字体,并将其大小设置为12。

接下来,我将文本显示在PDF页面上,并使用contentStream.close()方法关闭PDPageContentStream对象。

最后,我将文档保存为"one-more.pdf"文件,然后关闭PDDocument对象。效果如下图:

万猫学社

读取PDF文件

我们可以使用以下代码读取PDF文件中的全部内容:

import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;public class ReadPDFExample {public static void main(String[] args) {// 创建文件对象File file = new File("one-more.pdf");try {// 创建 PDF 文档对象PDDocument document = PDDocument.load(file);// 创建 PDF 文本剥离器PDFTextStripper stripper = new PDFTextStripper();// 获取 PDF 文件的全部内容String text = stripper.getText(document);// 输出 PDF 文件的全部内容System.out.println(text);// 关闭 PDF 文档对象document.close();} catch (IOException e) {e.printStackTrace();}}
}

首先,创建一个文件对象,然后使用 PDDocument 类的静态方法 load() 加载 PDF 文件并创建一个 PDF 文档对象。

然后,我们创建一个 PDFTextStripper 对象,并使用它的 getText() 方法获取 PDF 文件的全部内容。

最后,我们输出 PDF 文件的全部内容,并关闭 PDF 文档对象。

输出内容就是之前我们写入的:

Hello, World!

插入图片

我们可以使用以下代码在PDF文件中插入图片:

import java.io.File;
import java.io.IOException;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;public class InsertImageInPDF {public static void main(String[] args) {try {// 加载PDF文件PDDocument document = PDDocument.load(new File("one-more.pdf"));// 获取第一页PDPage page = document.getPage(0);// 加载图像文件PDImageXObject image = PDImageXObject.createFromFile("one-more.jpg", document);// 在指定位置插入图像PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true, true);contentStream.drawImage(image, 200, 500, image.getWidth(), image.getHeight());// 关闭流contentStream.close();// 保存修改后的PDF文件document.save("one-more-jpg.pdf");// 关闭文档document.close();System.out.println("PDF created successfully.");} catch (IOException e) {e.printStackTrace();}}
}

在这个例子中,我们加载了一个名为“one-more.pdf”的PDF文件,获取了第一页,并加载了一个名为“one-more.jpg”的图像文件。

然后,我们使用drawImage()方法在PDF文档中的指定位置插入了图像。

最后,我们将修改后的文档保存到名为“one-more-jpg.pdf”的新文件中,并关闭文档。效果如下图:

读取图片

我们可以使用以下代码在PDF文件中读取图片:

import java.io.IOException;
import java.util.List;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;public class ReadPDFImagesExample {public static void main(String[] args) {try {// 加载PDF文件PDDocument document = PDDocument.load(new File("one-more-jpg.pdf"));PDPageTree pageTree = document.getPages();// 遍历每个页面for (PDPage page : pageTree) {int pageNum = pageTree.indexOf(page) + 1;int count = 1;System.out.println("Page " + pageNum + ":");for (COSName xObjectName : page.getResources().getXObjectNames()) {PDXObject pdxObject = page.getResources().getXObject(xObjectName);if (pdxObject instanceof PDImageXObject) {PDImageXObject image = (PDImageXObject) pdxObject;System.out.println("Found image with width "+ image.getWidth()+ "px and height "+ image.getHeight()+ "px.");String fileName = "one-more-" + pageNum + "-" + count + ".jpg";ImageIO.write(image.getImage(), "jpg", new File(fileName));count++;}}}document.close();} catch (IOException e) {e.printStackTrace();}}
}

在此示例中,我们使用PDDocument类从指定的PDF文件中加载文档,并遍历每个页面以查找其中的图像。

对于每个页面,我们获取其资源(包括图像)并检查其中是否存在图像。

如果存在,则我们遍历它们,并使用PDImageXObject对象获取它们的属性,例如宽度和高度。

然后,使用ImageIO把图片保存到本地文件系统。

输出如下:

Page 1:
Found image with width 150px and height 150px.

结尾

Apache PDFBox 是一款功能丰富的工具,除了上述特性外,还有许多其他功能等待我们去探索和挖掘。如果您对 Apache PDFBox 有任何疑问或想了解更多功能,请随时在评论区向我提问,或者直接访问官方网站:https://pdfbox.apache.org/。

相关文章:

使用 Apache PDFBox 操作PDF文件

简介 Apache PDFBox库是一个开源的Java工具&#xff0c;专门用于处理PDF文档。它允许用户创建全新的PDF文件&#xff0c;编辑现有的PDF文档&#xff0c;以及从PDF文件中提取内容。此外&#xff0c;Apache PDFBox还提供了一些命令行实用工具。 Apache PDFBox提供了创建、渲染、…...

【Python 常用脚本及命令系列 3.2 -- 检测到弹框跳出然后关掉它--脚本实现】

文章目录 简介脚本实现 简介 在Python中&#xff0c;你可以使用第三方库如pyautogui和pygetwindow来检测屏幕上的弹框并关闭它。这些库可以模拟鼠标和键盘操作&#xff0c;也可以获取窗口信息。 首先&#xff0c;需要安装这些库&#xff08;如果你还没有安装的话&#xff09;&…...

junit单元测试:使用@ParameterizedTest 和 @CsvSource注解简化单元测试方法

在平常的开发工作中&#xff0c;我们经常需要写单元测试。比如&#xff0c;我们有一个校验接口&#xff0c;可能会返回多种错误信息。我们可以针对这个接口&#xff0c;写多个单元测试方法&#xff0c;然后将其场景覆盖全。那么&#xff0c;怎么才能写一个测试方法&#xff0c;…...

C# winform判断自身程序是否已运行,如果已运行则激活窗体

C# winform判断自身程序是否已运行&#xff0c;如果已运行则激活窗体 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using Syst…...

超维空间M1无人机使用说明书——21、基于opencv的人脸识别

引言&#xff1a;M1型号无人机不仅提供了yolo进行物体识别&#xff0c;也增加了基于opencv的人脸识别功能包&#xff0c;仅需要启动摄像头和识别节点即可 链接: 源码链接 一、一键启动摄像头和人脸识别节点 roslaunch robot_bringup bringup_face_detect.launch无报错&#…...

Redis 持久化——AOF

文章目录 为什么需要AOF?概念持久化查询和设置1. 查询AOF启动状态2. 开启AOF持久化2.1 命令行启动AOF2.2 配置文件启动 AOF 3. 触发持久化3.1 自动触发3.3 手动触发 4. AOF 文件重写4.1 什么是AOF重写&#xff1f;4.2 AOF 重写实现4.3 AOF 重写流程 5. 配置说明6. 数据恢复6.1…...

华为云服务介绍(二)

在 华为云服务介绍(一) 中我们看到华为云提供了一系列的云服务,包括计算、存储、网络、数据库、安全等方面的解决方案。通过灵活的系统架构设计,可以充分利用这些云服务技术,从而更好地满足用户的需求。 本文从系统架构的角度出发,通过充分利用华为云提供的各种云服务技…...

mysql列题

mysql列题 1.查询学过「张三」老师授课的同学的信息2.查询没有学全所有课程的同学的信息3.查询没学过"张三"老师讲授的任一门课程的学生姓名4.查询两门及其以上不及格课程的同学的学号&#xff0c;姓名及其平均成绩5.检索" 01 "课程分数小于 60&#xff0c…...

cpu缓存一致性

文章目录 cpu缓存一致性缓存的出现&#xff1a;多核之后带来的缓存一致性问题&#xff0c;如何解决LOCK 指令&#xff08;刚好可以实现上述的目标&#xff09;LOCK 指令特性内存屏障特性编译器屏障的作用MESI协议为什么有了 MESI协议 还需要 内存屏障问题&#xff1a;总结&…...

Android Framework 常见解决方案(25-1)定制CPUSET解决方案-framework部分修改

1 原理说明 这个方案有如下基本需求&#xff1a; 构建自定义CPUSET&#xff0c;/dev/cpuset中包含一个全新的cpuset分组。且可以通过set_cpuset_policy和set_sched_policy接口可以设置自定义CPUSET。开机启动后可以通过zygote判定来对特定的应用进程设置CPUSET&#xff0c;并…...

PyTorch 参数化深度解析:自定义、管理和优化模型参数

目录 torch.nn子模块parametrize parametrize.register_parametrization 主要特性和用途 使用场景 参数和关键字参数 注意事项 示例 parametrize.remove_parametrizations 功能和用途 参数 返回值 异常 使用示例 parametrize.cached 功能和用途 如何使用 示例…...

自承载 Self-Host ASP.NET Web API 1 (C#)

本教程介绍如何在控制台应用程序中托管 Web API。 ASP.NET Web API不需要 IIS。 可以在自己的主机进程中自托管 Web API。 创建控制台应用程序项目 启动 Visual Studio&#xff0c;然后从“开始”页中选择“新建项目”。 或者&#xff0c;从“ 文件 ”菜单中选择“ 新建 ”&a…...

Vue2-子传父和父传子的基本用法

在Vue 2中&#xff0c;可以使用props和$emit来实现子组件向父组件传值&#xff08;子传父&#xff09;和父组件向子组件传值&#xff08;父传子&#xff09;。 子传父&#xff08;子组件向父组件传值&#xff09;的基本用法如下&#xff1a; 在父组件中定义一个属性&#xff…...

使用numpy处理图片——镜像翻转和旋转

在《使用numpy处理图片——基础操作》一文中&#xff0c;我们介绍了如何使用numpy修改图片的透明度。本文我们将介绍镜像翻转和旋转。 镜像翻转 上下翻转 from PIL import Image import numpy as np img Image.open(example.png) data np.array(img)# axis0 is vertical, a…...

HTML5 article标签,<time>...</time>标签和pubdate属性的运用

1、<article>...</article>标签的运用 article标签代表文档、页面或应用程序中独立的、完整的、可以独自被外部引用的内容。它可以是一篇博客或报竟杂志中的文章、一篇论坛帖子、一段用户评论或一个独立的插件&#xff0c;或者其他任何独立的内容。把文章正文放在h…...

Amazing OpenAI API:把非 OpenAI 模型都按 OpenAI API 调用

分享一个有趣的小工具&#xff0c;10MB 身材的小工具&#xff0c;能够将各种不同的模型 API 转换为开箱即用的 OpenAI API 格式。 让许多依赖 OpenAI API 的软件能够借助开发者能够接触到的&#xff0c;非 OpenAI 的 API 私有部署和使用起来。 写在前面 这个小工具软件写于两…...

RK3568平台开发系列讲解(驱动篇)pinctrl 函数操作集结构体讲解

🚀返回专栏总目录 文章目录 一、pinctrl_ops二、pinmux_ops三、pinconf_ops沉淀、分享、成长,让自己和他人都能有所收获!😄 pinctrl_ops:提供有关属于引脚组的引脚的信息。pinmux_ops:选择连接到该引脚的功能。pinconf_ops:设置引脚属性(上拉,下拉,开漏,强度等)。…...

vue购物车案例,v-model 之 lazy、number、trim,与后端交互

购物车案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"./js/vue.js"></script> </head> <body> <div id"d1"&…...

云原生Kubernetes: Kubeadm部署K8S 1.29版本 单Master架构

目录 一、实验 1.环境 2.K8S master节点环境准备 3.K8S master节点安装kubelet、kubeadm、kubectl 3.K8S node节点环境准备与软件安装 4.K8S master节点部署服务 5.K8S node节点部署 6.K8S master节点查看集群 7.容器网络&#xff08;CNI&#xff09;部署 8.K8S 集群…...

C++协程操作

什么是C++协程 C++中的协程是一种用户态轻量级线程,它拥有自己的上下文和栈,并且协程的切换和调度由用户定义,不需要陷入内核。如同一个进程可以拥有多个线程,一个线程也可以拥有多个协程。协程的优点在于极高的执行效率,因为协程切换不需要陷入内核,而是由用户程序定义切…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...