从PDF中删除空注释

时间:2017-02-15 21:44:23

标签: c# itext

我写了一个C#程序来删除没有PDF文件操作的注释。我使用iTextSharp。但是,在我的一个文件中,删除了一个非空注释(它的JavaScript动作),而其他非空注释则被删除。是这样的吗?是因为我的代码还是有问题PDF file

using System;
using System.IO;
using iTextSharp.text.pdf;

namespace removeEmpty
{
    class Program
    {
        public static void Main()
        {
            //Bytes will hold our final PDFs
            byte[] bytes;

            using (var ms = new MemoryStream()) {
                using (var reader = new PdfReader("sandri6.pdf")) {
                    using (var stamper = new PdfStamper(reader, ms)) {
                        for (int i = 1; i <= reader.NumberOfPages; i++) {
                            // get a page a PDF page
                            PdfDictionary page = reader.GetPageN(i);
                            // get all the annotations of page i
                            PdfArray annotationsArray = page.GetAsArray(PdfName.ANNOTS);

                            // if page does not have annotations
                            if (annotationsArray == null) {
                                continue;
                            }

                            // for each annotation
                            for (int j = 0; j < annotationsArray.Size; j++) {
                                // for current annotation
                                PdfDictionary currentAnnotation = annotationsArray.GetAsDict(j);

                                PdfDictionary annotationAction = currentAnnotation.GetAsDict(PdfName.AA);
                                if (annotationAction == null) {
                                    annotationsArray.Remove(j);
                                    Console.Write("Removed annotation {0} with no action from page {1}\n", j, i);
                                }
                            }
                        }   
                    }
                }

                //grab the bytes before closing things out
                bytes = ms.ToArray();
            }

            //write thebytes to disk
            File.WriteAllBytes("output.pdf", bytes);
            Console.ReadKey();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您提供的文档在其唯一页面上包含13个链接注释。与您的假设(所有注释都有关联的操作)相反,第二个没有操作,因此,您的代码正确删除了该操作:

Annotations screenshot

如您所见,对象778中的第二个注释没有 A 条目。

因此,如果您的示例文档,您的代码可以正常工作。

请注意,某些注释类型不仅可以具有标准操作( A 条目),它们还可以(或者代之以!)具有响应各种触发事件的其他操作。因此,对于通用解决方案,您还必须在这些类型的注释中检查 AA 条目。

但是,代码中存在错误,即使它未在示例文档中触发。在注释删除循环中,我们看到:

for (int j = 0; j < annotationsArray.Size; j++) {
    // for current annotation
    PdfDictionary currentAnnotation = annotationsArray.GetAsDict(j);

    PdfDictionary annotationAction = currentAnnotation.GetAsDict(PdfName.A);
    if (annotationAction == null) {
        annotationsArray.Remove(j);
        Console.Write("Removed annotation {0} with no action from page {1}\n", j, i);
    }
}

现在让我们假设我们有一个文档,其中包含两个连续注释的页面而没有操作。针对该文档运行代码,只会删除第一个,而不是第二个,因为annotationsArray.Remove(j)将注释移到j+1到位置j,然后循环变量递增,即删除之后的注释根本没有测试过!

你可以通过向后循环来解决这个问题,即

for (int j = annotationsArray.Size - 1; j >= 0; j--)

j来电后递减annotationsArray.Remove(j)

向后循环的优点是Console输出更有意义,在后一种情况下,注释索引并不总是表示原始数组中的索引,仅在当前中间数组中。