PDFBox迁移PDF文本保留格式遇编码及字体子类问题求助
PDF文本迁移与字体格式保留问题解决方案
需求背景
- 将原PDF文本迁移至新PDF,需完整保留粗体、斜体、下划线等字体格式
- 实现方案:基于原PDF的
TextPosition列表提取字体、字号信息,通过PDPageContentStream.showText()写入文本
已解决问题
- 问题1:循环执行137次后抛出异常:
java.lang.IllegalArgumentException: No glyph for U+00AD in font VVHOEY+FrutigerLT-BoldCn- 解决方式:手动将Unicode
U+00AD(软连字符)替换为占位符
- 解决方式:手动将Unicode
当前核心问题
- 问题2:调用
org.apache.pdfbox.pdmodel.font.PDCIDFontType0.encode(int)时抛出UnsupportedOperationException- 尝试替换源文档对应字体时,出现
COSStream随机关闭导致新文档无法保存 - 使用
PDType1Font.HELVETICA等标准字体可正常工作,但需保留原文档的7个子集字体(subtype 1或0,无AcroForm定义)
- 尝试替换源文档对应字体时,出现
针对性解决方案
1. 解决CIDFontType0编码异常
- 避免直接调用
encode(int)方法:PDCIDFontType0的单字符编码方法未实现,改用PDFont.encode(String)处理整段文本编码,该方法会自动适配CID字体的编码逻辑:String targetText = textPosition.getUnicode(); byte[] encodedData = textPosition.getFont().encode(targetText); contentStream.showText(encodedData); - 直接复用原字体实例:从
TextPosition中直接获取原PDFont对象,不要重新加载或创建字体实例,避免触发未实现的编码逻辑:TextPosition textPos = ...; // 原文档提取的TextPosition对象 PDFont originalFont = textPos.getFont(); contentStream.setFont(originalFont, textPos.getFontSize()); contentStream.showText(textPos.getUnicode()); - 前置检测字符可用性:子集字体可能缺失部分字符,提前检测并替换缺失字符:
PDFont font = ...; String rawText = ...; StringBuilder processedText = new StringBuilder(); for (char c : rawText.toCharArray()) { if (font.hasGlyph(c)) { processedText.append(c); } else { processedText.append("□"); // 用占位符替代缺失字形 } } contentStream.showText(processedText.toString());
2. 解决COSStream随机关闭问题
- 禁止手动关闭字体流:复用原文档字体时,不要调用
font.getCOSObject().close()等可能关闭流的方法,PDFBox会在文档保存阶段自动管理流资源 - 绑定字体到新文档资源:将原字体添加到新页面的资源集合中,确保资源引用有效:
PDPage newPage = new PDPage(); PDResources resources = new PDResources(); resources.add(originalFont); newPage.setResources(resources); newDocument.addPage(newPage);
内容的提问来源于stack exchange,提问作者DummerIdiot
相关产品推荐
相关产品推荐

