合并PDF出现OOM异常
- 优化方法一:使用PdfSmartCopy类代替PdfCopy类。这个类可以在合并PDF文件时,检测并消除重复的对象,从而减少内存的占用。您可以参考以下代码示例:
//创建一个Document对象
Document document = new Document();//创建一个PdfSmartCopy对象
PdfSmartCopy copy = new PdfSmartCopy(document, new FileOutputStream("output.pdf"));//打开Document对象
document.open();//创建一个PdfReader对象
PdfReader reader = null;//遍历要合并的PDF文件
for (String file : files) {//加载PDF文件reader = new PdfReader(file);//获取PDF文件的总页数int n = reader.getNumberOfPages();//遍历每一页,添加到PdfSmartCopy对象中for (int page = 0; page < n;) {copy.addPage(copy.getImportedPage(reader, ++page));}
}//关闭PdfReader对象
reader.close();//关闭Document对象
document.close();//创建一个PdfStamper对象
PdfStamper stamper = new PdfStamper(new PdfReader("output.pdf"), new FileOutputStream("output.pdf"));//获取总页数
int pageCount = stamper.getReader().getNumberOfPages();//遍历每一页,添加页码
for (int i = 1; i <= pageCount; i++) {//获取当前页PdfContentByte content = stamper.getOverContent(i);//设置字体和颜色content.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), 12);content.setRGBColorFill(0, 0, 0);//获取当前页的宽度和高度Rectangle pageSize = stamper.getReader().getPageSize(i);float width = pageSize.getWidth();float height = pageSize.getHeight();//计算页码的位置float x = width / 2;float y = 10;//添加页码content.beginText();content.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + i + "页,共" + pageCount + "页", x, y, 0);content.endText();
}//关闭PdfStamper对象
stamper.close();
- 优化方法二:使用PdfWriter类代替PdfCopy类。这个类可以在合并PDF文件时,直接将每一页写入到输出流中,而不需要将整个文档加载到内存中。可以参考以下代码示例:
//创建一个Document对象
Document document = new Document();//创建一个PdfWriter对象
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));//打开Document对象
document.open();//创建一个PdfImportedPage对象
PdfImportedPage page = null;//创建一个PdfReader对象
PdfReader reader = null;//遍历要合并的PDF文件
for (String file : files) {//加载PDF文件reader = new PdfReader(file);//获取PDF文件的总页数int n = reader.getNumberOfPages();//遍历每一页,添加到PdfWriter对象中for (int i = 1; i <= n; i++) {//获取当前页的宽度和高度Rectangle pageSize = reader.getPageSizeWithRotation(i);float width = pageSize.getWidth();float height = pageSize.getHeight();//设置Document对象的页面大小document.setPageSize(pageSize);//创建一个新的页面document.newPage();//导入当前页page = writer.getImportedPage(reader, i);//将当前页添加到PdfWriter对象中writer.addPageDictEntry(PdfName.ROTATE, pageSize.getRotationAsPageDictEntry());writer.addDirectImageSimple(page);writer.getCurrentPage().add(page);//创建一个PdfContentByte对象PdfContentByte content = writer.getDirectContent();//设置字体和颜色content.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), 12);content.setRGBColorFill(0, 0, 0);//计算页码的位置float x = width / 2;float y = 10;//添加页码content.beginText();content.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + i + "页,共" + pageCount + "页", x, y, 0);content.endText();}
}//关闭PdfReader对象
reader.close();//关闭Document对象
document.close();
- 优化方法三:使用PdfReader类的partial和selectPages方法。这些方法可以在加载PDF文件时,只读取需要的页面,而不需要将整个文档加载到内存中。可以参考以下代码示例:
//创建一个Document对象
Document document = new Document();//创建一个PdfCopy对象
PdfCopy copy = new PdfCopy(document, new FileOutputStream("output.pdf"));//打开Document对象
document.open();//创建一个PdfReader对象
PdfReader reader = null;//遍历要合并的PDF文件
for (String file : files) {//设置partial为true,只读取需要的页面reader = new PdfReader(new RandomAccessFileOrArray(file), null);reader.consolidateNamedDestinations();reader.partial = true;//获取PDF文件的总页数int n = reader.getNumberOfPages();//创建一个List对象,存储需要的页面List<Integer> pages = new ArrayList<Integer>();//遍历每一页,添加到List对象中for (int i = 1; i <= n; i++) {pages.add(i);}//使用selectPages方法,只选择需要的页面reader.selectPages(pages);//将选择的页面添加到PdfCopy对象中for (int i = 0; i < pages.size(); ) {copy.addPage(copy.getImportedPage(reader, ++i));}
}//关闭PdfReader对象
reader.close();//关闭Document对象
document.close();//创建一个PdfStamper对象
PdfStamper stamper = new PdfStamper(new PdfReader("output.pdf"), new FileOutputStream("output.pdf"));//获取总页数
int pageCount = stamper.getReader().getNumberOfPages();//遍历每一页,添加页码
for (int i = 1; i <= pageCount; i++) {//获取当前页PdfContentByte content = stamper.getOverContent(i);//设置字体和颜色content.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), 12);content.setRGBColorFill(0, 0, 0);//获取当前页的宽度和高度Rectangle pageSize = stamper.getReader().getPageSize(i);float width = pageSize.getWidth();float height = pageSize.getHeight();//计算页码的位置float x = width / 2;float y = 10;//添加页码content.beginText();content.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + i + "页,共" + pageCount + "页", x, y, 0);content.endText();
}//关闭PdfStamper对象
stamper.close();
[java - How to avoid OutOfMemoryError when merging PDFs using iText? - Stack Overflow]
[java - How to merge pdf files without loading all the documents in memory? - Stack Overflow]
[java - How to merge pdf files without loading all the documents in memory? - Stack Overflow]
相关文章:
合并PDF出现OOM异常
优化方法一:使用PdfSmartCopy类代替PdfCopy类。这个类可以在合并PDF文件时,检测并消除重复的对象,从而减少内存的占用。您可以参考以下代码示例: //创建一个Document对象 Document document new Document();//创建一个PdfSmartC…...
c语言-数据结构-链式二叉树
目录 1、二叉树的概念及结构 2、二叉树的遍历概念 2.1 二叉树的前序遍历 2.2 二叉树的中序遍历 2.3 二叉树的后序遍历 2.4 二叉树的层序遍历 3、创建一颗二叉树 4、递归方法实现二叉树前、中、后遍历 4.1 实现前序遍历 4.2 实现中序遍历 4.3 实现后序遍历 5、…...
DelayQueue介绍
5.1 DelayQueue介绍&应用 DelayQueue就是一个延迟队列,生产者写入一个消息,这个消息还有直接被消费的延迟时间。 需要让消息具有延迟的特性。 DelayQueue也是基于二叉堆结构实现的,甚至本事就是基于PriorityQueue实现的功能。二叉堆结构…...
centos8 redis 6.2.6源码安装+主从哨兵
文章目录 centos8 redis 6.2.6源码安装主从哨兵下载解压编译安装配置配置systemd服务启停及开机启动登录验证主从同步配置哨兵哨兵注册systemd centos8 redis 6.2.6源码安装主从哨兵 单机安装 下载解压 cd /data wget http://download.redis.io/releases/redis-6.2.6.tar.gz…...
机器学习之危险品车辆目标检测
危险品的运输涉及从离开仓库到由车辆运输到目的地的风险。监控事故、车辆运动动态以及车辆通过特定区域的频率对于监督车辆运输危险品的过程至关重要。 在线工具推荐: 三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数…...
DHCP协议及实验omnipeek抓包工具分析 IPv4协议
一 抓包命令 adb shell tcpdump -i wlan0 -w /data/tcpdump.pcap 抓包后截图如下 二 DHCP是什么 2.1 DHCP定义 DHCP( Dynamic Host Configuration Protocol, 动态主机配置协议)定义: 存在于应用层(OSI) 前身是BOOTP(Bootstrap Protocol)协议 是一个使用UDP(User …...
考过了PMP,面试的时候应该怎么办?
近期喜番在后台收到了很多同学们的私信,表示自己已经过了8月份的PMP考试,开始着手往项目管理岗位转型,但是对于项目管理岗位的面试却一筹莫展。放轻松,大家的需求喜番都了解了,喜番给大家总结了一些项目经理在面试的时…...
技巧-PyTorch中num_works的作用和实验测试
简介 在 PyTorch 中,num_workers 是 DataLoader 中的一个参数,用于控制数据加载的并发线程数。它允许您在数据加载过程中使用多个线程,以提高数据加载的效率。 具体来说,num_workers 参数指定了 DataLoader 在加载数据时将创建的…...
Android:FragmentTransaction
上一篇Android:FragmentTransaction我们大概介绍了FragmentManager的大致工作流程,知道了每个动作都会添加到Op队列里,并由FragmentTransaction进行管理,那么我们就来看看FragmentTransaction的具体内容。 首先FragmentTransacti…...
5.golang字符串的拆解和拼接
字符串是 Go 中的字节切片。可以通过将一组字符括在双引号中来创建字符串" "。Go 中的字符串是兼容Unicode编码的,并且是UTF-8编码的。 访问字符串的单个字节或字符 由于字符串是字节切片,因此可以访问字符串的每个字节。 func printStr(s …...
配置 Mantis 在 Windows 上的步骤
配置 Mantis Bug Tracker 在 Windows 上的步骤 Mantis Bug Tracker 是一款开源的缺陷跟踪系统,用于管理软件开发中的问题和缺陷。在 Windows 环境下配置 Mantis 可以帮助开发者更方便地进行项目管理。以下是一个详细的教程,包含了 EasyPHP Devserver 和…...
Android 单元测试初体验(二)-断言
[TOC](Android 单元测试初体验(二)-断言) 前言 当初在学校学安卓的时候,老师敢教学进度,翻到单元测试这一章节的时候提了两句,没有把单元测试当重点讲,只是说我们工作中几乎不会用到,果真在之前的几年工作当中我真的没…...
通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示
通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(一) 图片数据转成base64编码方式 #include <ros/ros.h> #include <signal.h> #include <sensor_msgs/Image.h> #include <message_filters/subscriber.h> #include <message_filt…...
【 Kubernetes 风云录 】- Istio 应用多版本流量控制
文章目录 原理实现DeploymentVirtualServiceDestinationRule 约束部署 目的: 根据不同的引擎版本,可以把请求发送到指定的引擎上。可以实现版本降级。 原理 Istio通过VirtualService和DestinationRule两个资源对象来实现流量管理,其中VirtualService用于…...
比尔盖茨:GPT-5不会比GPT-4好多少,生成式AI已达到极限
比尔盖茨一句爆料,成为机器学习社区热议焦点: “GPT-5不会比GPT-4好多少。” 虽然他已不再正式参与微软的日常运营,但仍在担任顾问,并且熟悉OpenAI领导团队的想法。 消息来自德国《商报》(Handelsblatt)对…...
let const 与var的区别
1、let可以形成块级作用域,在es6之前javascript只有函数作用域,没有块级作用域。在es6之前实现块级作用域: 2、可以看到通过一个立即执行函数表达式,我们实现了一个局部作用域或者块级作用域,但是有了let之后就不需要写这样的代…...
git 把项目托管到码云
码云: 把项目托管到码云 1.注册并微活码云账号(https://gitee.com/] 2.牛成井前博 SSH公钥 (运行 ssh -t gitgitee.com 构测 SSH 公明是否有开成功) 3.创建率户的码人伦;库 4.把本地项口上传到码云对应的空白仓库中 第一:上传个新项目 cd existing_git_…...
sCrypt 现已支持各类主流前端框架
sCrypt 现已支持各类主流前端框架,包括: ReactNext.jsAngularSvelteVue 3.x or 2.x bundled with Vite or Webpack 通过在这些支持的前端框架中集成sCrypt开发环境,你可以直接在前端项目里访问合约实例和调用合约,方便用户使用Se…...
leetcode:2549. 统计桌面上的不同数字(python3解法)
难度:简单 给你一个正整数 n ,开始时,它放在桌面上。在 109 天内,每天都要执行下述步骤: 对于出现在桌面上的每个数字 x ,找出符合 1 < i < n 且满足 x % i 1 的所有数字 i 。然后,将这些…...
数据结构 / day03作业
1.顺序表按元素删除 //main.c#include "head.h" int main(int argc, const char *argv[]) {sqlist *listcreate_space();// printf("&list%p\n", list);int n;int index;data_type element, key;printf("please input n;");scanf("%d&…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
npm install 相关命令
npm install 相关命令 基本安装命令 # 安装 package.json 中列出的所有依赖 npm install npm i # 简写形式# 安装特定包 npm install <package-name># 安装特定版本 npm install <package-name><version>依赖类型选项 # 安装为生产依赖(默认&…...
Linux【5】-----编译和烧写Linux系统镜像(RK3568)
参考:讯为 1、文件系统 不同的文件系统组成了:debian、ubuntu、buildroot、qt等系统 每个文件系统的uboot和kernel是一样的 2、源码目录介绍 目录 3、正式编译 编译脚本build.sh 帮助内容如下: Available options: uboot …...
claude3.7高阶玩法,生成系统架构图,国内直接使用
文章目录 零、前言一、操作指南操作指导 二、提示词模板三、实战图书管理系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 在线考试系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 四、感受 零、前言 现在很多AI大模型可以…...
