gpt4 book ai didi

footer - iText 7 - 最后一页的不同页脚 - PdfDictionary 中的空指针

转载 作者:行者123 更新时间:2023-12-03 23:54:52 40 4
gpt4 key购买 nike

我正在尝试在 iText7 中实现页脚,页脚在文档的最后一页上应该不同,我添加了一个事件处理程序,当文档关闭时调用该事件处理程序,但尝试在页面上循环会导致空指针异常:

java.lang.NullPointerException
at com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:482)
at com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:152)
at com.itextpdf.kernel.pdf.PdfPage.newContentStream(PdfPage.java:777)
at com.itextpdf.kernel.pdf.PdfPage.newContentStreamBefore(PdfPage.java:212)

这是我试图实现的代码:
private void onCloseDocument(
final PdfDocument document, final float xpos, final float ypos)
{

for (int i = 1; i <= document.getPdfDocument().getNumberOfPages(); i++)
{
final PdfPage page = document.getPdfDocument().getPage(i);
final PdfCanvas canvas =
new PdfCanvas(page.newContentStreamBefore(), page.getResources(), document.getPdfDocument());
canvas.beginText();
canvas.setFontAndSize(document.getFont(), FONT_SIZE);
canvas.setLeading(14.4F);

canvas.moveText(xpos, ypos);

if (i == document.getPdfDocument().getNumberOfPages())
{
canvas.showText("Last page");
}
else
{
canvas.showText("Another page");
}

canvas.endText();
canvas.stroke();
canvas.release();
}
}

最初我认为这行得通,因为我正在插入一个区域中断来让 pdf 分成两页,但是当我添加更多内容并且页面自然增加时,我会得到这个异常,同样我现在已经通过尝试插入多个区域中断,我得到了同样的异常(exception)。

注意*我发现如果我设置 immediateFlush创建文档时设置为 false 则我没有遇到此问题。

这样做是否有重大的性能损失\缺点?

最佳答案

你的方法
正如你自己发现的那样,

if I set immediateFlush to false when creating the document then I do not get this issue.


原因是 itext 通常会尝试将数据写入输出流并尽早释放内存,以免留下太大的内存占用。因此,你的方法

I have added an event handler which is called when the document is closed [...] trying to then loop over the pages


在该循环期间,通常会尝试操作其内容已从页面对象中刷新和删除的页面。
设置 immediateFlushfalse防止这种情况。不利的一面是你使用了更多的内存,因为现在更多的 pdf 被保存在内存中直到结束。
另一种方法
另一种方法是使用正常的 END_PAGE事件监听器模式。您可以为这样的事件监听器提供一些方法来通知它哪个页面将是最后一个。当事件监听器被触发时,它可以检查它当前是否正在处理该页面,在这种情况下,它可以绘制一个替代页脚,例如像这样:

class TextFooterEventHandler implements IEventHandler {
Document doc;
PdfPage lastPage = null;

public TextFooterEventHandler(Document doc) {
this.doc = doc;
}

@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfCanvas canvas = new PdfCanvas(docEvent.getPage());
Rectangle pageSize = docEvent.getPage().getPageSize();
canvas.beginText();
try {
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA_OBLIQUE), 5);
} catch (IOException e) {
e.printStackTrace();
}
if (lastPage == docEvent.getPage()) {
canvas.moveText((pageSize.getRight() - doc.getRightMargin() - (pageSize.getLeft() + doc.getLeftMargin())) / 2 + doc.getLeftMargin(), pageSize.getTop() - doc.getTopMargin() + 10)
.showText("VERY SPAECIAL LAST PAGE HEADER")
.moveText(0, (pageSize.getBottom() + doc.getBottomMargin()) - (pageSize.getTop() - doc.getTopMargin()) - 20)
.showText("VERY SPAECIAL LAST PAGE FOOTER")
.endText()
.release();
} else {
canvas.moveText((pageSize.getRight() - doc.getRightMargin() - (pageSize.getLeft() + doc.getLeftMargin())) / 2 + doc.getLeftMargin(), pageSize.getTop() - doc.getTopMargin() + 10)
.showText("this is a header")
.moveText(0, (pageSize.getBottom() + doc.getBottomMargin()) - (pageSize.getTop() - doc.getTopMargin()) - 20)
.showText("this is a footer")
.endText()
.release();
}
}
}
(在 CreateSpecificFooters 中的内部类)
你可以这样使用它:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new File("differentLastPageFooter.pdf")));
Document doc = new Document(pdfDoc);
TextFooterEventHandler eventHandler = new TextFooterEventHandler(doc);
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, eventHandler);
for (int i = 0; i < 12; i++) {
doc.add(new Paragraph("Test " + i + " Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."));
}

// the currently last page is also the last page of the document, so inform the event listener
eventHandler.lastPage = pdfDoc.getLastPage();
doc.close();
( CreateSpecificFooters 测试 testDifferentLastPageFooter )
您可能已经观察到,与我的原始评论相反

you can give that event listener some method to signal to it that the next event to come will be for the special case.


我在这里并没有将“下一个即将发生的事件”表示为特殊,而是“为给定的页面对象将发生的下一个事件”。原因是 iText 7 页面事件触发时有一些延迟,因此当我发出上述信号时,可能尚未触发最后一个页面之前的事件。
顺便说一下,我基于 iText 示例类 com.itextpdf.samples.sandbox.events.TextFooter .样本类 VariableHeader在同一个包裹中似乎表明我最初的想法(标志着“下一个即将到来的事件”是特别的)应该有效。不过,不同之处在于,在该示例中,页面是通过输入 AreaBreak 来切换的。对象到文档。这似乎会提前触发事件。但是,通常情况下,您无法确定页面何时切换,因此通常您还应该为事件监听器提供页面以验证它是否具有要特殊处理的正确页面。

关于footer - iText 7 - 最后一页的不同页脚 - PdfDictionary 中的空指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50236085/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com