2013-05-10 27 views
1

我正在嘗試創建一個自動填充的政府工資表窗體,其中涉及可變頁數的可能性。我目前正在將每個頁面存儲爲一個Map,其中的鍵是字段的名稱,值是它們的內容。 目前,我有這樣的代碼:嘗試使用iText生成可變頁面PDF時出現異常

in = new FileInputStream(inputPDF); 
PdfCopyFields adder = new PdfCopyFields(outStream); 
PdfReader reader = null; 
PdfStamper stamper = null; 
ByteArrayOutputStream baos = null; 
for (int pageNum = 0; pageNum < numPages; pageNum++) { 
    reader = new PdfReader(in); 
    baos = new ByteArrayOutputStream(); 
    stamper = new PdfStamper(reader, baos); 
    AcroFields form = stamper.getAcroFields(); 
    Map<String, String> page = pages.get(pageNum); 
    setFieldsToPage(form, pageNum); 
    populatePage(form, page, pageNum); 
    stamper.close(); 
    reader = new PdfReader(baos.toByteArray()); 
    adder.addDocument(reader); 
} 

調用的方法是:

private void populatePage(AcroFields form, Map<String, String> pageMap, int pageNum) throws Exception { 
    ArrayList<String> fieldNames = new ArrayList<String>(); 
    for (String key : pageMap.keySet()) { 
     fieldNames.add(key); 
    } 
    for (String key : fieldNames) { 
     form.setField(key + pageNum, pageMap.get(key)); 
    } 
} 

private void setFieldsToPage(AcroFields form, int pageNum) { 
    ArrayList<String> fieldNames = new ArrayList<String>(); 
    Map<String, AcroFields.Item> fields = form.getFields(); 
    for (String fieldName : fields.keySet()) { 
     fieldNames.add(fieldName); 
    } 
    for (String fieldName : fieldNames) { 
     form.renameField(fieldName, fieldName + pageNum); 
    } 
} 

的問題是,這將引發通過對第二次迭代異常循環:在reader = new PdfReader(in);我得到以下異常: java.io.IOException: PDF header signature not found. 我在做什麼錯了^ h是嗎,我該如何解決?

編輯: 這裏是例外:

java.io.IOException: PDF header signature not found. 
    at com.lowagie.text.pdf.PRTokeniser.checkPdfHeader(Unknown Source) 
    at com.lowagie.text.pdf.PdfReader.readPdf(Unknown Source) 
    at com.lowagie.text.pdf.PdfReader.<init>(Unknown Source) 
    at com.lowagie.text.pdf.PdfReader.<init>(Unknown Source) 

順便說一句,對不起,如果格式是壞的 - 這是使用計算器我的第一次。

+1

你的問題很好,但是粘貼完整的堆棧跟蹤或至少是其中很大一部分會很有幫助。 – 2013-05-10 22:07:11

回答

2

你的問題是,你基本上是嘗試多次讀取相同的輸入流,而這是第一次之後已經定位在其結束:

in = new FileInputStream(inputPDF); 
[...] 
for (int pageNum = 0; pageNum < numPages; pageNum++) { 
    reader = new PdfReader(in); 
    [...] 
} 

整個流在第一次迭代讀取;因此,在第二個new PdfReader(in)基本上試圖解析導致你

java.io.IOException的一個空文件:PDF頭標識未發現

您可以修復,通過簡單地構建PdfReader輸入文件路徑直接每次:

for (int pageNum = 0; pageNum < numPages; pageNum++) { 
    reader = new PdfReader(inputPDF); 
    [...] 
} 

兩件事,但:

  • 使用後,您不會關閉您的PdfReader實例。在最新的iText版本中,讀者的隱式關閉已被從代碼中取出,因爲它與許多用例相沖突。因此,在您完成讀取器工作後(包括使用該讀取器的任何壓模等也關閉)後,您應該明確關閉讀取器。

  • 一般來說,如果你在你的文件系統有一個PDF已經通過一個FileInputStream打開PdfReader因爲這是非常浪費資源的明智---與輸入流初始化的讀者第一個完全讀取流入內存(byte []),然後解析內存中的表示;用文件路徑初始化的閱讀器直接解析光盤表示。

+0

請接受mkl的回答。我已經提高了效率,因爲它更詳細,它不僅解釋了問題的原因,而且還提供了正確使用iText的建議。 (正如我是iText的作者,我經常厭倦人們「做錯了」,你必須原諒我) – 2013-05-11 12:19:02

+0

謝謝,這工作(一旦我記得實際上關閉加法器)。布魯諾,你原諒了。 – dais314 2013-05-13 13:57:32

0

的異常告訴你,你正在閱讀的文件不具有%PDF-啓動。

寫一個不涉及iText的小例子,檢查InputStream in的前5個字節,你會發現你做錯了什麼(我們不能告訴你,除非你告訴我們這5個字節) 。

+0

這確實相當於「%PDF-」,但正如mkl在他的回答中所說的,您正在重新使用InputStream,這意味着有時您會嘗試從頭開始讀取文件,而不是從頭開始。 – 2013-05-13 13:46:59

相關問題