You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 10:04:58