Java 尝试使用iText生成可变页面PDF时出现异常

Java 尝试使用iText生成可变页面PDF时出现异常,java,pdf,pdf-generation,itext,Java,Pdf,Pdf Generation,Itext,我正在尝试创建一个自动填充的PDF政府工资单表单,其中可能涉及到可变页数。我目前将每个页面存储为一个映射,键是字段的名称,值是字段的内容。 目前,我有以下代码: in = new FileInputStream(inputPDF); PdfCopyFields adder = new PdfCopyFields(outStream); PdfReader reader = null; PdfStamper stamper = null; ByteArrayOutputStream baos =

我正在尝试创建一个自动填充的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);
}

顺便说一下,如果格式不好,我很抱歉-这是我第一次使用stackoverflow。

异常告诉您,您正在读取的文件不是以
%PDF-
开头的


写一个不涉及iText的小例子,检查中输入流的前5个字节,你会发现你做错了什么(除非你向我们展示这5个字节,否则我们无法告诉你).

您的问题在于,您实际上尝试多次读取同一输入流,而第一次读取后,该输入流已经位于其末尾:

in = new FileInputStream(inputPDF);
[...]
for (int pageNum = 0; pageNum < numPages; pageNum++) {
    reader = new PdfReader(in);
    [...]
}
不过,还有两件事:

  • 使用后,您不会关闭
    PdfReader
    实例。在最新的iText版本中,隐式关闭读卡器已经从代码中删除,因为它与许多用例相冲突。因此,在您完成读卡器的工作后(这包括使用该读卡器的任何压模等也被关闭),您应该显式地关闭读卡器

  • 一般来说,如果您的文件系统中已经有PDF,那么通过
    文件输入流
    打开PDF阅读器是非常浪费资源的——使用输入流初始化的读取器首先将该流完全读入内存(字节[]),然后解析内存中的表示形式;用文件路径初始化的读卡器直接解析光盘表示


您的问题很好,但是粘贴完整的堆栈跟踪,或者至少粘贴其中的一部分会有所帮助。请接受mkl的回答。我对它投了更高的票,因为它更详细,它不仅解释了问题的原因,而且还为您提供了正确使用iText的建议。(因为我是iText的作者,我经常对人们“做错了”感到厌倦。你必须原谅我。)谢谢,这很有效(一旦我记得关闭adder)。布鲁诺,你被原谅了。这确实相当于“%PDF-”,但正如mkl在他的回答中所说的,你在重复使用输入流,这意味着有时候,你尝试从文件的末尾而不是从开始读取文件。
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);
    }
}
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)
in = new FileInputStream(inputPDF);
[...]
for (int pageNum = 0; pageNum < numPages; pageNum++) {
    reader = new PdfReader(in);
    [...]
}
for (int pageNum = 0; pageNum < numPages; pageNum++) {
    reader = new PdfReader(inputPDF);
    [...]
}