2013-05-10 28 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

相关问题