Aspose.PDF Java替换PDF文本时遇固定大小集合异常求助
问题:Aspose.PDF Java替换特定文本时抛出"Collection is of a fixed size"异常
问题背景
- 场景:使用Aspose.PDF Java API对PDF中的PII数据脱敏,替换为混淆文本
- PDF内目标文本(顺序如下):
- B, KATILDE
- A, RICHARD
- S, NARTURO
- 使用版本:Aspose.PDF 23.7,Gradle依赖配置:
implementation group: 'com.aspose', name: 'aspose-pdf', version: '23.7' - 异常现象:
- 可成功替换
B, KATILDE - 替换
A, RICHARD或S, NARTURO时抛出固定大小集合异常 - 单独替换
RICHARD或NARTURO可成功执行
- 可成功替换
示例代码
private void replaceTextInDocument(String sourceDoc, String destDoc, String textToReplace, String replacementText) { Document pdfDocument = new Document(sourceDoc); System.out.println("replaceTextInDocument processing: " + textToReplace); // 创建TextAbsorber查找目标文本 TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber(textToReplace); pdfDocument.getPages().accept(textFragmentAbsorber); // 获取提取到的文本片段集合 TextFragmentCollection textFragmentCollection = textFragmentAbsorber.getTextFragments(); // 遍历片段并替换 for (TextFragment textFragment : (Iterable<TextFragment>) textFragmentCollection) { // 更新文本及样式 textFragment.setText(replacementText); textFragment.getTextState().setFont(FontRepository.findFont("Verdana")); textFragment.getTextState().setFontSize(8); textFragment.getTextState().setForegroundColor(Color.getBlack()); textFragment.getTextState().setBackgroundColor(Color.getWhite()); } // 保存修改后的PDF pdfDocument.save(destDoc); pdfDocument.close(); }
异常信息
Exception in thread "main" com.aspose.pdf.internal.ms.System.l7k: **Collection is of a fixed size** at com.aspose.pdf.internal.ms.System.ly$lb.removeAt(Unknown Source) at com.aspose.pdf.ADocument.lI(Unknown Source) at com.aspose.pdf.CharInfoCollection.copyTo(Unknown Source) at com.aspose.pdf.l19y.lI(Unknown Source) at com.aspose.pdf.l19y.lf(Unknown Source) at com.aspose.pdf.TextFragment.lf(Unknown Source) at com.aspose.pdf.TextFragment.setText(Unknown Source)
解决思路与方案
1. 根本原因分析
该异常是因为目标文本对应的TextFragment内部的CharInfoCollection为固定大小集合,直接调用setText()需要修改这个集合,但固定大小集合不允许添加/删除元素。这种情况多发生在PDF文本被内部拆分、特殊编码存储的场景。
2. 可行解决方案
方案一:替换为删除原片段+插入新文本
绕过直接修改固定大小集合的逻辑,先删除原文本片段,再在相同位置插入新文本:
private void replaceTextInDocument(String sourceDoc, String destDoc, String textToReplace, String replacementText) { Document pdfDocument = new Document(sourceDoc); System.out.println("replaceTextInDocument processing: " + textToReplace); TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber(textToReplace); pdfDocument.getPages().accept(textFragmentAbsorber); TextFragmentCollection textFragmentCollection = textFragmentAbsorber.getTextFragments(); // 使用迭代器遍历,避免集合修改导致的遍历异常 java.util.Iterator<TextFragment> iterator = textFragmentCollection.iterator(); while (iterator.hasNext()) { TextFragment textFragment = iterator.next(); Page page = textFragment.getPage(); Rectangle rect = textFragment.getRectangle(); // 删除原文本片段 iterator.remove(); page.getParagraphs().delete(textFragment); // 创建新文本片段并设置位置和样式 TextFragment newText = new TextFragment(replacementText); newText.setPosition(new Position(rect.getLLX(), rect.getLLY())); newText.getTextState().setFont(FontRepository.findFont("Verdana")); newText.getTextState().setFontSize(8); newText.getTextState().setForegroundColor(Color.getBlack()); newText.getTextState().setBackgroundColor(Color.getWhite()); // 添加新文本到页面 page.getParagraphs().add(newText); } pdfDocument.save(destDoc); pdfDocument.close(); }
方案二:拆分目标文本进行替换
既然单独替换名字部分(如RICHARD)可行,可以将完整文本拆分为前缀+名字分别替换,注意添加匹配限制避免误替换:
// 替换"A, RICHARD"时,分两步处理 replaceTextInDocument(sourceDoc, tempDoc, "A, ", "X, "); replaceTextInDocument(tempDoc, destDoc, "RICHARD", "XXX");
方案三:升级Aspose.PDF版本
该问题可能是23.7版本的已知bug,尝试升级到更高版本(如24.x系列),官方可能已修复固定集合修改的兼容性问题。
方案四:排查PDF文本结构
添加调试代码,查看目标文本的片段拆分情况:
for (TextFragment textFragment : (Iterable<TextFragment>) textFragmentCollection) { System.out.println("片段内容:" + textFragment.getText()); System.out.println("字符集合是否固定大小:" + ((java.util.Collection)textFragment.getCharacters()).isFixedSize()); }
如果发现目标文本被拆分为多个片段,可调整匹配逻辑合并处理。
内容的提问来源于stack exchange,提问作者Manchanda. P
相关产品推荐
相关产品推荐

