2017-02-15 110 views
0

我編寫了一個C#程序,用於從PDF文件中刪除沒有任何操作的註釋。我使用iTextSharp。但是,在我的一個文件中,刪除了一個非空註釋(這是JavaScript操作),而其他非空註釋未被刪除。是這樣嗎?是因爲我的代碼還是有問題PDF file從PDF中刪除空註釋

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

您提供的文檔在其唯一頁面上包含13個鏈接註釋。並在對比的假設(即所有註釋有相關的行動),第二個沒有動作,因此,正確的代碼刪除:

Annotations screenshot

正如你看到的,第二個註解在對象778中沒有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--) 

或被annotationsArray.Remove(j)調用後遞減j

向後循環的優點是Console輸出更有意義,在後一種情況下,註釋索引並不總是表示原始數組中的索引,而僅表示當前中間數組中的索引。

+0

謝謝你的回答。這是否意味着** AA **入門商店JavaScript在第二個註釋中。我很困惑,因爲在另一個[文件](https://www.upload.ee/files/6680430/sandri6.pdf.html)註釋是空的(Adobe Acrobat如此說),它們不會被代碼刪除。我該如何解決? – menteith

+0

@menteith *「這是否意味着AA條目將JavaScript存儲在第二個註釋中。」* - 否如截圖所示,第二個註釋既沒有** A也沒有** AA **條目。 – mkl

+0

@menteith關於你的其他文件:我無法重現你的觀察。恰恰那些沒有動作的註釋(正好是作者名稱周圍的鏈接註釋)被刪除。我通過檢查PDF對象並單擊Acrobat進行檢查。 – mkl