求推荐Java中实现双PDF分别高亮差异并保留原文件的开源方案
Java实现独立高亮两个PDF差异并保留原文件的开源方案
方案一:PDFBox自定义改造
你提到PDFBox默认会合并双PDF,那可以跳过它的内置对比逻辑,自己拆分流程:
- 分别加载两个原始PDF,用
PDFTextStripper或PDFTextStripperByArea提取每页的文本及位置信息 - 用第三方文本对比库(比如Apache Commons Text的
DiffUtils)找出两段文本的差异片段 - 对每个原始PDF的副本,通过
PDPageContentStream在差异文本对应的BoundingBox上绘制半透明高亮矩形,完全保留原PDF内容 - 将两个处理后的PDF(原内容+独立高亮)按顺序合并到输出文件,还可按需添加分隔页区分
示例代码片段:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.text.PDFTextStripper; import org.apache.commons.text.diff.DiffUtils; import org.apache.commons.text.diff.Patch; import java.io.File; import java.awt.Color; import java.util.Arrays; public class PdfDiffHighlighter { public static void main(String[] args) throws Exception { // 加载原始PDF文档 PDDocument doc1 = PDDocument.load(new File("original1.pdf")); PDDocument doc2 = PDDocument.load(new File("original2.pdf")); PDDocument outputDoc = new PDDocument(); int pageCount = Math.min(doc1.getNumberOfPages(), doc2.getNumberOfPages()); PDFTextStripper stripper = new PDFTextStripper(); for (int i = 0; i < pageCount; i++) { PDPage page1 = doc1.getPage(i); PDPage page2 = doc2.getPage(i); // 提取每页文本 stripper.setStartPage(i + 1); stripper.setEndPage(i + 1); String text1 = stripper.getText(doc1); String text2 = stripper.getText(doc2); // 对比文本差异 Patch<String> patch = DiffUtils.diff(Arrays.asList(text1.split("\n")), Arrays.asList(text2.split("\n"))); // 给doc1的页面添加高亮(这里需补充根据文本定位坐标的逻辑) PDPageContentStream cs1 = new PDPageContentStream(doc1, page1, PDPageContentStream.AppendMode.APPEND, true, true); cs1.setNonStrokingColor(new Color(255, 255, 0, 128)); // 遍历差异片段,定位并绘制高亮矩形 patch.getDeltas().forEach(delta -> { // 示例:假设已获取到差异区域的坐标x,y,width,height try { cs1.addRect(100, 500, 200, 20); cs1.fill(); } catch (Exception e) { e.printStackTrace(); } }); cs1.close(); // 同理处理doc2的页面高亮 PDPageContentStream cs2 = new PDPageContentStream(doc2, page2, PDPageContentStream.AppendMode.APPEND, true, true); cs2.setNonStrokingColor(new Color(0, 255, 255, 128)); // 绘制doc2的差异高亮 cs2.close(); } // 合并处理后的两个PDF到输出文件 doc1.getPages().forEach(outputDoc::addPage); // 可选:添加分隔页 outputDoc.addPage(new PDPage()); doc2.getPages().forEach(outputDoc::addPage); outputDoc.save("highlighted_diff.pdf"); // 关闭资源 doc1.close(); doc2.close(); outputDoc.close(); } }
方案二:iText 7实现
iText 7的文本定位API更精准,适合处理复杂排版的PDF:
- 使用
PdfTextExtractor提取每个字符的位置和内容,精准定位差异区域 - 对原始PDF副本,通过
PdfCanvas绘制高亮批注 - 合并两个带高亮的PDF到输出文件,保留各自原内容
核心优势是处理多列、图文混排的PDF时,文本定位准确率更高。
关键注意事项
- 文本定位是核心:对于复杂布局,需要遍历
TextRenderInfo获取每个字符的坐标,再映射到差异片段的位置 - 依赖文本对比库:优先用Apache Commons Text的
DiffUtils或Google的diff-match-patch,避免自己造轮子 - 操作副本:务必对原始PDF的副本进行修改,防止破坏原文件
内容的提问来源于stack exchange,提问作者Aneek Biswas
相关产品推荐
相关产品推荐

