我写了一个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();
}
}
}
答案 0 :(得分:1)
您提供的文档在其唯一页面上包含13个链接注释。与您的假设(所有注释都有关联的操作)相反,第二个没有操作,因此,您的代码正确删除了该操作:
如您所见,对象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
输出更有意义,在后一种情况下,注释索引并不总是表示原始数组中的索引,仅在当前中间数组中。