我正在尝试创建政府工资表单的自动填写PDF,其中涉及可变页数的可能性。我目前正在将每个页面存储为Map,其中键是字段的名称,值是其内容。 目前,我有这段代码:
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。
答案 0 :(得分: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 []),然后解析内存中的表示;用文件路径初始化的阅读器直接解析光盘表示。
答案 1 :(得分:0)
例外情况告诉您,您正在阅读的文件不以%PDF-
开头。
写一个不涉及iText的小例子并检查InputStream in
的前5个字节,你会发现你做错了什么(除非你告诉我们,否则我们无法告诉你5个字节)。