使用iText 5合并PDF时,因PdfReader默认持有文件锁导致源PDF无法删除;根本解决方法是通过FileInputStream显式构造PdfReader,确保JVM能及时释放底层文件句柄。
使用itext 5合并pdf时,因`pdfreader`默认持有文件锁导致源pdf无法删除;根本解决方法是通过`fileinputstream`显式构造`pdfreader`,确保jvm能及时释放底层文件句柄。
在基于iText 5进行PDF合并的典型场景中,开发者常遇到一个隐蔽但高频的问题:合并操作成功完成,但后续尝试删除原始PDF文件(如File.delete()或自定义FileTools.deleteFile())始终失败,返回false。即使已显式调用reader.close()和copy.freeReader(reader),文件仍被占用——这并非代码逻辑遗漏,而是iText 5在Java 9+环境下与文件系统资源管理的兼容性缺陷所致。
根本原因:隐式文件句柄未释放
iText 5的PdfReader(String filename)构造器内部会直接打开RandomAccessFile并长期持有句柄,不依赖InputStream生命周期。即使调用reader.close(),该句柄也可能因JVM垃圾回收延迟或底层OS缓存未及时释放,导致文件处于“被进程占用”状态,从而阻止操作系统执行删除操作。
正确实践:显式使用FileInputStream
解决方案是绕过PdfReader对文件路径的直接处理,改用FileInputStream作为数据源构造PdfReader。此时,PdfReader仅读取流内容,不独占文件句柄;当FileInputStream关闭(且PdfReader.close()被调用)后,系统资源可立即释放:
public static void pdfConcat2(String pathFile1, String pathFile2, String destinationPDF) {
Document document = null;
FileOutputStream outputStream = null;
PdfCopy copy = null;
PdfReader reader = null;
try {
document = new Document();
outputStream = new FileOutputStream(destinationPDF);
copy = new PdfSmartCopy(document, outputStream);
document.open();
// ✅ 关键修复:使用 FileInputStream 显式构造 PdfReader
try (FileInputStream fis1 = new FileInputStream(pathFile1)) {
reader = new PdfReader(fis1);
copy.addDocument(reader);
copy.freeReader(reader);
reader.close(); // 确保 reader 资源释放
}
try (FileInputStream fis2 = new FileInputStream(pathFile2)) {
reader = new PdfReader(fis2);
copy.addDocument(reader);
copy.freeReader(reader);
reader.close();
}
// ✅ 安全关闭所有资源
document.close();
outputStream.flush();
outputStream.close();
copy.flush();
copy.close();
} catch (Exception e) {
e.printStackTrace();
// 建议在此处添加资源强制清理逻辑(如 try-with-resources 外的 finally)
}
}注意事项与最佳实践
- 必须配合try-with-resources或显式close():FileInputStream需在PdfReader使用后立即关闭,否则仍可能残留句柄;示例中采用嵌套try-with-resources确保流自动释放。
- 避免重复使用同一PdfReader实例:每个源文件应创建独立PdfReader,且freeReader()与close()缺一不可。
- 升级建议:iText 5已停止维护,该问题在iText 7中已彻底修复(其PdfDocument基于NIO.2设计,资源管理更健壮)。新项目应优先迁移到iText 7,并使用PdfMerger类替代手动PdfCopy流程。
- Windows系统特别提示:文件锁行为在Windows上尤为严格,测试务必在目标运行环境验证删除逻辑,避免仅依赖Linux/macOS表现。
遵循上述方案后,FileTools.deleteFile()等删除操作将稳定返回true,实现PDF合并与源文件清理的可靠闭环。










