Java PDFBox删除注释保留删除线

Java PDFBox删除注释保留删除线,java,pdf,pdfbox,Java,Pdf,Pdfbox,我有一个PDF,其中有一个段落的评论。这一段删节了。我的要求是从特定页面删除该命令 下面的代码应该从我的PDF中删除一条特定的注释,但它不会 PDDocument document = PDDocument.load(...File...); List<PDAnnotation> annotations = new ArrayList<>(); PDPageTree allPages = document.getDocumentCatalog().getPages();

我有一个PDF,其中有一个段落的评论。这一段删节了。我的要求是从特定页面删除该命令

下面的代码应该从我的PDF中删除一条特定的注释,但它不会

PDDocument document = PDDocument.load(...File...);
List<PDAnnotation> annotations = new ArrayList<>();
PDPageTree allPages = document.getDocumentCatalog().getPages();

for (int i = 0; i < allPages.getCount(); i++) {
    PDPage page = allPages.get(i);
    annotations = page.getAnnotations();

    List<PDAnnotation> annotationToRemove = new ArrayList<PDAnnotation>();

    if (annotations.size() < 1)
        continue;
    else {
        for (PDAnnotation annotation : annotations) {

            if (annotation.getContents() != null && annotation.getContents().equals("Sample Strikethrough")) {
                annotationToRemove.add(annotation);
            }
        }
        annotations.removeAll(annotationToRemove);
    }
}
PDDocument document=PDDocument.load(…文件…);
列表注释=新建ArrayList();
PDPageTree allPages=document.getDocumentCatalog().getPages();
对于(int i=0;i
删除特定注释并在应用注释的文本上保留删除线的最佳方法是什么

删除特定注释并在应用注释的文本上保留删除线的最佳方法是什么

您找到的注释实际上是子类型为删除线的文本标记注释,即此注释的主要外观是删除线。因此,您不能删除此注释。相反,您应该删除从中生成附加注释外观(悬停文本)的数据

可以这样做:

final COSName POPUP = COSName.getPDFName("Popup");

PDDocument document = PDDocument.load(resource);
List<PDAnnotation> annotations = new ArrayList<>();
PDPageTree allPages = document.getDocumentCatalog().getPages();

List<COSObjectable> objectsToRemove = new ArrayList<>();

for (int i = 0; i < allPages.getCount(); i++) {
    PDPage page = allPages.get(i);
    annotations = page.getAnnotations();

    for (PDAnnotation annotation : annotations) {
        if ("StrikeOut".equals(annotation.getSubtype()))
        {
            COSDictionary annotationDict = annotation.getCOSObject();
            COSBase popup = annotationDict.getItem(POPUP);
            annotationDict.removeItem(POPUP);            // popup annotation
            annotationDict.removeItem(COSName.CONTENTS); // plain text comment
            annotationDict.removeItem(COSName.RC);       // rich text comment
            annotationDict.removeItem(COSName.T);        // author

            if (popup != null)
                objectsToRemove.add(popup);
        }
    }

    annotations.removeAll(objectsToRemove);
}
final COSName POPUP=COSName.getPDFName(“POPUP”);
PDDocument document=PDDocument.load(资源);
列表注释=新建ArrayList();
PDPageTree allPages=document.getDocumentCatalog().getPages();
List objectsToRemove=new ArrayList();
对于(int i=0;i
(测试
testremovelikestephan


研究这个问题的一个副作用是PDFBox bug变得很明显:OP的原始代码本应完全删除删除删除注释,但它什么也没做。原因是在页面注释上下文中使用
cosaraylist
类时出现错误

page.getAnnotations()
返回的页面批注列表是
cosaraylist
的一个实例。此类包含COS对象在页面Annots数组中显示的列表,以及这些条目的包装器列表(在必要时解析间接引用之后)

removeAll
方法(明智地)检查其参数集合中是否存在此类包装器,并从前一个集合和后一个集合中按原样(即使用包装器)删除实际的COS对象,而不是包装器

这适用于Annots数组中的直接对象,但是前一个列表中作为间接引用的条目没有正确删除,因为代码试图删除解析的注释字典,而该列表实际上包含间接引用

在本案中,导致删除未被回写。在更一般的情况下,结果甚至可能更奇怪,因为这两个列表现在有不同的大小。所以,面向索引的方法现在可以操作列表的非对应对象

(顺便说一句,在我上面的代码中,我删除了一个间接引用,而不是包装器,使列表也变得混乱,因为这一次只删除了前者的一个条目,而不是后者的一个条目;可能这也应该得到更安全的处理。)

retainal
方法中也出现类似问题

另一个小故障:
cosaraylist.lastIndexOf
使用所包含列表的
indexOf

对此进行分析的PDFBox源代码是当前的3.0.0-SNAPSHOT,但所有版本2.0.0-2.0.7都会出现错误,因此他们的代码很可能也包含这些错误

删除特定注释并在应用注释的文本上保留删除线的最佳方法是什么

您找到的注释实际上是子类型为删除线的文本标记注释,即此注释的主要外观是删除线。因此,您不能删除此注释。相反,您应该删除从中生成附加注释外观(悬停文本)的数据

可以这样做:

final COSName POPUP = COSName.getPDFName("Popup");

PDDocument document = PDDocument.load(resource);
List<PDAnnotation> annotations = new ArrayList<>();
PDPageTree allPages = document.getDocumentCatalog().getPages();

List<COSObjectable> objectsToRemove = new ArrayList<>();

for (int i = 0; i < allPages.getCount(); i++) {
    PDPage page = allPages.get(i);
    annotations = page.getAnnotations();

    for (PDAnnotation annotation : annotations) {
        if ("StrikeOut".equals(annotation.getSubtype()))
        {
            COSDictionary annotationDict = annotation.getCOSObject();
            COSBase popup = annotationDict.getItem(POPUP);
            annotationDict.removeItem(POPUP);            // popup annotation
            annotationDict.removeItem(COSName.CONTENTS); // plain text comment
            annotationDict.removeItem(COSName.RC);       // rich text comment
            annotationDict.removeItem(COSName.T);        // author

            if (popup != null)
                objectsToRemove.add(popup);
        }
    }

    annotations.removeAll(objectsToRemove);
}
final COSName POPUP=COSName.getPDFName(“POPUP”);
PDDocument document=PDDocument.load(资源);
列表注释=新建ArrayList();
PDPageTree allPages=document.getDocumentCatalog().getPages();
List objectsToRemove=new ArrayList();
对于(int i=0;i