Java PDF操作指南:iText与PDFBox实战对比
1. Java操作PDF的常见场景与工具选型PDF作为跨平台文档格式在企业级应用中有着广泛的使用场景。Java开发者经常需要处理PDF文档的生成、编辑和内容提取等需求。从发票生成、报表导出到合同签署PDF操作几乎成为Java后台开发的标配技能。目前主流的Java PDF操作库主要有以下几个iText功能最全面的开源库支持PDF生成、编辑、加密等全套操作AGPL/commercial双协议Apache PDFBoxApache旗下的开源项目专注PDF内容提取和基础操作OpenPDFiText分支版本LGPL协议更友好Flying Saucer适合HTML转PDF场景JasperReports报表工具内置PDF导出功能对于数据写入场景iText和PDFBox是最常用的选择。iText在生成复杂PDF时更具优势而PDFBox在已有PDF修改方面更轻量。我们以iText 7为例进行演示这是目前最新的商业友好版本。2. 基础环境准备与依赖配置2.1 Maven依赖配置使用iText 7需要添加以下依赖到pom.xmldependency groupIdcom.itextpdf/groupId artifactIditext7-core/artifactId version7.2.5/version typepom/type /dependency如果需要处理中文等亚洲字符还需添加额外的字体模块dependency groupIdcom.itextpdf/groupId artifactIdfont-asian/artifactId version7.2.5/version /dependency2.2 字体资源准备处理中文内容时必须明确指定支持中文的字体。推荐将字体文件(.ttf)放在resources/fonts目录下。常用开源字体如思源黑体(Source Han Sans)阿里巴巴普惠体文泉驿系列字体注意直接使用系统字体可能导致部署环境缺少对应字体而出错建议将字体文件随项目一起打包。3. 基础文本写入实现3.1 创建PDF文档基础框架以下是创建PDF并写入文本的最小实现import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; public class BasicPdfWriter { public static void main(String[] args) throws Exception { // 1. 创建PdfWriter指向输出文件 PdfWriter writer new PdfWriter(output.pdf); // 2. 创建PdfDocument对象 PdfDocument pdf new PdfDocument(writer); // 3. 创建Document对象用于添加内容 Document document new Document(pdf); // 4. 添加段落内容 document.add(new Paragraph(Hello PDF World!)); // 5. 关闭文档 document.close(); } }3.2 中文内容处理处理中文需要特别注意字体设置// 加载字体(假设resources/fonts下有SourceHanSans.ttf) PdfFont font PdfFontFactory.createFont( fonts/SourceHanSans.ttf, PdfEncodings.IDENTITY_H, true); // 创建支持中文的段落 Paragraph p new Paragraph(这是一个中文段落) .setFont(font) .setFontSize(14); document.add(p);3.3 文本样式控制iText提供了丰富的文本样式控制Paragraph styledText new Paragraph() .add(new Text(加粗文本).setBold()) .add( ) .add(new Text(斜体文本).setItalic()) .add( ) .add(new Text(红色文本).setFontColor(Color.RED)) .add( ) .add(new Text(带背景色).setBackgroundColor(Color.YELLOW)) .setFont(font) .setFontSize(12);4. 高级数据写入技巧4.1 表格数据写入表格是数据展示的常见形式iText表格操作示例// 创建3列表格 Table table new Table(new float[]{1, 2, 1}); // 添加表头 table.addHeaderCell(new Cell().add(new Paragraph(ID).setBold())); table.addHeaderCell(new Cell().add(new Paragraph(商品名称).setBold())); table.addHeaderCell(new Cell().add(new Paragraph(价格).setBold())); // 添加数据行 for(Product product : productList) { table.addCell(new Cell().add(new Paragraph(product.getId()))); table.addCell(new Cell().add(new Paragraph(product.getName()))); table.addCell(new Cell().add(new Paragraph(product.getPrice()))); } // 设置表格宽度占页面80% table.setWidth(UnitValue.createPercentValue(80)); // 添加到文档 document.add(table);4.2 列表数据展示有序列表和无序列表的实现// 无序列表 List list new List() .setSymbolIndent(12) .setListSymbol(•) .setFont(font); list.add(列表项1); list.add(列表项2); document.add(list); // 有序列表 List numberedList new List(ListNumberingType.DECIMAL); numberedList.add(第一项); numberedList.add(第二项); document.add(numberedList);4.3 图片插入处理插入图片到PDF的完整流程// 加载图片(假设在resources/images下) ImageData imageData ImageDataFactory.create(images/logo.png); Image image new Image(imageData); // 设置图片属性 image.setAutoScale(true); // 自动缩放 image.setHorizontalAlignment(HorizontalAlignment.CENTER); // 居中 // 添加到文档 document.add(image);提示处理大图片时建议先压缩避免PDF体积过大。iText支持JPEG、PNG、BMP等多种格式。5. 页面布局与样式控制5.1 页面大小与边距创建文档时指定页面属性// 自定义页面大小(A4竖版) PageSize pageSize PageSize.A4; Document document new Document(pdfDoc, pageSize); // 设置页边距(上下左右) document.setMargins(50, 30, 50, 30);5.2 分页与页眉页脚添加页眉页脚的实现方式// 总页数 int totalPages pdfDoc.getNumberOfPages(); // 为每页添加页脚 for (int i 1; i totalPages; i) { PdfPage page pdfDoc.getPage(i); Rectangle pageSize page.getPageSize(); // 在页面底部创建Canvas Canvas canvas new Canvas(page, pageSize); float y 20; // 距离底部20单位 // 添加页脚文本 canvas.showTextAligned( new Paragraph(String.format(第 %d 页/共 %d 页, i, totalPages)) .setFontSize(10), pageSize.getWidth() / 2, y, TextAlignment.CENTER); canvas.close(); }5.3 多栏布局创建类似报纸的多栏布局// 创建两栏布局 ColumnDocumentRenderer renderer new ColumnDocumentRenderer( document, new float[]{250, 250} // 两栏宽度 ); document.setRenderer(renderer); // 添加内容时会自动分栏 document.add(new Paragraph(第一栏内容...)); document.add(new Paragraph(第二栏内容...));6. 常见问题排查6.1 中文乱码问题中文显示异常通常由以下原因导致未正确设置支持中文的字体字体编码未使用PdfEncodings.IDENTITY_H字体文件路径错误或未打包到最终jar中解决方案// 确保使用以下方式加载字体 PdfFont font PdfFontFactory.createFont( fonts/YourChineseFont.ttf, PdfEncodings.IDENTITY_H, true);6.2 内存泄漏问题iText操作PDF时需要及时关闭资源try (PdfWriter writer new PdfWriter(outputPath); PdfDocument pdf new PdfDocument(writer); Document doc new Document(pdf)) { // 操作文档 } catch (Exception e) { e.printStackTrace(); }6.3 性能优化建议处理大批量数据时使用PdfWriter.setSmartMode(true)启用智能模式对于大型表格考虑分页显示图片使用适当压缩质量复用字体等资源对象7. 实际应用案例7.1 生成销售报表典型销售报表生成流程public void generateSalesReport(ListSaleRecord records, String outputPath) throws IOException { // 初始化文档 PdfWriter writer new PdfWriter(outputPath); PdfDocument pdf new PdfDocument(writer); Document document new Document(pdf, PageSize.A4.rotate()); // 横向A4 // 添加标题 document.add(new Paragraph(月度销售报表) .setFont(titleFont) .setFontSize(18) .setTextAlignment(TextAlignment.CENTER)); // 添加生成日期 document.add(new Paragraph(生成日期: LocalDate.now()) .setFont(bodyFont) .setFontSize(10)); // 创建表格 Table table new Table(new float[]{1, 3, 2, 2, 2}); table.setWidth(UnitValue.createPercentValue(100)); // 添加表头 addTableHeader(table); // 添加数据行 for (SaleRecord record : records) { addTableRow(table, record); } // 添加表格到文档 document.add(table); // 添加统计信息 addSummary(document); document.close(); }7.2 合同文档生成合同生成的关键要点使用固定格式模板关键字段高亮显示添加数字签名区域设置文档权限// 合同关键信息高亮示例 Paragraph contractItem new Paragraph() .add(甲方: ) .add(new Text(partyA).setUnderline()) .add( 乙方: ) .add(new Text(partyB).setUnderline()); document.add(contractItem); // 添加签名区域 Table signatureTable new Table(2); signatureTable.addCell(new Cell().add(new Paragraph(甲方签字:))); signatureTable.addCell(new Cell().add(new Paragraph(乙方签字:))); signatureTable.addCell(new Cell().setHeight(50)); // 留空签字处 signatureTable.addCell(new Cell().setHeight(50)); document.add(signatureTable);8. 扩展功能实现8.1 PDF加密与权限控制设置文档打开密码和权限WriterProperties props new WriterProperties() .setStandardEncryption( userPass.getBytes(), // 用户密码 ownerPass.getBytes(), // 所有者密码 EncryptionConstants.ALLOW_PRINTING, // 允许打印 EncryptionConstants.ENCRYPTION_AES_256 // 加密强度 ); PdfWriter writer new PdfWriter(outputPath, props);8.2 添加条形码/二维码使用Barcode4J集成生成条形码// 生成二维码 BarcodeQRCode qrCode new BarcodeQRCode(https://example.com); Image qrCodeImage new Image(qrCode.createFormXObject(pdf)); document.add(qrCodeImage);8.3 动态水印添加为PDF添加文字水印for (int i 1; i pdf.getNumberOfPages(); i) { PdfPage page pdf.getPage(i); PdfCanvas canvas new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdf); // 设置水印样式 canvas.saveState() .setFillColor(Color.LIGHT_GRAY) .setFontAndSize(font, 40) .beginText(); // 在页面中心添加旋转文字 canvas.showTextAligned(CONFIDENTIAL, page.getPageSize().getWidth() / 2, page.getPageSize().getHeight() / 2, i, TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45); canvas.restoreState(); }9. 最佳实践与性能优化9.1 对象复用提升性能避免重复创建相同资源// 在文档级别共享字体等资源 PdfFont sharedFont PdfFontFactory.createFont(...); Style sharedStyle new Style() .setFont(sharedFont) .setFontSize(12); // 在多个段落中复用 Paragraph p1 new Paragraph(段落1).addStyle(sharedStyle); Paragraph p2 new Paragraph(段落2).addStyle(sharedStyle);9.2 大文档分块处理处理大型PDF时的内存管理// 启用智能模式减少内存占用 writer.setSmartMode(true); // 定期释放资源 if(docCounter % 100 0) { document.flush(); System.gc(); }9.3 错误处理与日志记录完善的错误处理机制try { // PDF操作代码 } catch (PdfException e) { logger.error(PDF处理错误: {}, e.getMessage()); throw new BusinessException(PDF生成失败, e); } catch (IOException e) { logger.error(IO异常: {}, e.getMessage()); throw new BusinessException(文件操作失败, e); } finally { // 确保资源释放 IOUtils.closeQuietly(document); IOUtils.closeQuietly(pdf); IOUtils.closeQuietly(writer); }10. 替代方案比较10.1 iText vs PDFBox特性iTextPDFBox生成PDF功能强大API丰富基础功能完善修改PDF支持但较复杂简单直接中文支持需要额外配置字体同左性能中等较高许可协议AGPL/CommercialApache 2.0学习曲线较陡峭较平缓10.2 HTML转PDF方案对于已有HTML内容的情况Flying Saucer Thymeleaf/Freemarker// 使用模板引擎渲染HTML String htmlContent templateEngine.process(template, context); // 转换为PDF OutputStream os new FileOutputStream(output.pdf); ITextRenderer renderer new ITextRenderer(); renderer.setDocumentFromString(htmlContent); renderer.layout(); renderer.createPDF(os); os.close();OpenHTMLToPDF更现代的替代方案10.3 云端PDF生成服务对于无服务器环境需求AWS TextractGoogle Document AI阿里云智能媒体服务这些服务提供REST API接口适合分布式系统集成但需要考虑网络延迟和成本因素。

相关新闻

ARM GIC中断路由寄存器深度解析与多核系统配置实战

ARM GIC中断路由寄存器深度解析与多核系统配置实战

1. 从手册到实战:GIC中断路由寄存器深度解析 在嵌入式系统开发,尤其是基于ARM Cortex-A系列多核处理器的项目中,中断管理是决定系统稳定性和实时性的基石。很多开发者对Linux内核中的 request_irq 、 irq_set_affinity 等API耳熟能详&…

2026/9/24 8:41:56 阅读更多 →
AM62L MMC/SD控制器UHS-II寄存器配置与DMA优化实战

AM62L MMC/SD控制器UHS-II寄存器配置与DMA优化实战

1. 项目概述与核心价值在嵌入式系统开发,尤其是涉及高速存储接口的设计中,MMC/SD控制器是连接处理器与外部存储卡(如SD卡、eMMC芯片)的桥梁。它的性能直接决定了系统启动速度、数据读写效率乃至整个产品的用户体验。很多开发者可能…

2026/9/19 20:00:10 阅读更多 →
零基础玩转网页端多轨音频编辑,无需安装即刻创作

零基础玩转网页端多轨音频编辑,无需安装即刻创作

还在为下载安装庞大的音频编辑软件发愁?还在因为不懂复杂操作放弃音频创作?今天给大家推荐一款免安装、易上手的网页端多轨音频工作站——Inspire Pro,无论是音频剪辑、MIDI 编曲、混音后期,还是短视频配音、播客制作,…

2026/9/17 1:03:23 阅读更多 →

最新新闻

20页的复盘只动3页,AI改完其他页没乱

20页的复盘只动3页,AI改完其他页没乱

20页里只动3页 一位每天跟表格、文档打交道的人,手上刚做完一份月度复盘:一份数据表,加一份20页的汇报文件。开会前一天,他往表格里加了一张决策看板,又在汇报文件里挑出3页重排——其余17页,全都没动。 整…

2026/9/24 8:41:58 阅读更多 →
AI科研工具助力科研效率提升 解锁前沿学术研究新路径

AI科研工具助力科研效率提升 解锁前沿学术研究新路径

每次找到心仪的外国文献,却被付费墙冷冷地挡在外面,是不是感觉科研的热情瞬间被浇灭?作为学生党,我太懂这种无力感了。但好消息是,通过几个合法且免费的“通道”和技巧,我们完全能实现“文献自由”。今天分…

2026/9/24 8:41:58 阅读更多 →
Flink Hive 方言查询(Queries)完全指南:从 SELECT 语法到 Sort/Cluster/Join/CTE 实战

Flink Hive 方言查询(Queries)完全指南:从 SELECT 语法到 Sort/Cluster/Join/CTE 实战

大数据流处理批处理数据工程 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink 点击查看 免费下载 导读 Hive 方言是 Flink 为兼容 Hive 生态提供的 SQL 解析与执行模式:启用后,你可以直接在 Flink 中编写 HiveQ…

2026/9/24 8:41:58 阅读更多 →
EMC四大测试CE/RE/CS/RS本质解析与协同设计

EMC四大测试CE/RE/CS/RS本质解析与协同设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 8:41:58 阅读更多 →
LanceDB Node.js 多向量搜索:理解 MultiVector 类型别名与多向量查询实战

LanceDB Node.js 多向量搜索:理解 MultiVector 类型别名与多向量查询实战

向量数据库数据库人工智能后端 【免费下载链接】lancedb Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less. 项目地址: https://gitcode.com/gh_mirrors/la/lancedb 点击查看 免费下载 MultiVector 是 lancedb/lan…

2026/9/24 8:41:58 阅读更多 →
2026届美术生如何平衡专业课集训与文化课的学习节奏?

2026届美术生如何平衡专业课集训与文化课的学习节奏?

写作方向:实操方法型2026届美术生平衡专业课集训与文化课节奏的核心逻辑,不是每天对半切分学习时间,而是顺着集训全周期的阶段目标动态调整精力占比,把文化课拆解成“日常碎片化积累考后集中冲刺”两个模块,从根源上避…

2026/9/24 8:40:57 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →