1

我正在尝试创建政府工资单的自动填充 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. 我在这里做错了什么,我该如何解决?

编辑:这是一个例外:

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)

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

4

2 回答 2

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,则通过 a 为其打开一个 PdfReaderFileInputStream是非常浪费资源的 --- 使用输入流初始化的阅读器首先将该流完全读入内存 (byte[]) 并且然后解析内存中的表示;使用文件路径初始化的读取器直接解析磁盘表示。

于 2013-05-11T12:00:03.100 回答
0

异常告诉您您正在阅读的文件不是以%PDF-.

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

于 2013-05-11T06:49:09.307 回答