Ваш подход
Как вы сами выяснили,
, если при создании документа я установил значение immediateFlush
в ложь, тогда я не получу эту проблему.
Причина в том, что itext обычно пытается записать данные в выходной поток и освободить память как можно раньше, чтобы не оставить слишком большой объем памяти.Таким образом, ваш подход
Я добавил обработчик событий, который вызывается при закрытии документа [...], пытаясь затем перебрать страницы
во время этогоЦикл обычно пытается манипулировать страницами, содержимое которых уже было очищено и удалено из объекта страницы.
Установка immediateFlush
в false
предотвращает это.Недостатком является то, что вы используете больше памяти, потому что теперь намного больше 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 test testDifferentLastPageFooter
)
Вы, возможно, заметили, что в отличие от моего первоначального комментария
вы можете дать этому слушателю какой-то метод, чтобы сообщить ему, что следующее событие будет для специальногоcase.
Я здесь не сигнализирую, что «следующее событие наступит» как особенное, а вместо этого «следующее событие наступит для данного объекта страницы».Причина в том, что 7-страничные события iText запускаются с некоторой задержкой, поэтому, когда я даю сигнал, как указано выше, событие для страницы до последней, возможно, еще не было инициировано.
Кстати, я основалэтот пример в классе примеров iText com.itextpdf.samples.sandbox.events.TextFooter
.Класс сэмплов VariableHeader
в том же пакете указывает на то, что моя первоначальная мысль (, сигнализирующая, что «следующее событие наступит» должно быть особенным ) должна была сработать.Разница, однако, заключается в том, что в этом примере страницы переключаются путем подачи в документ AreaBreak
объектов.Это, кажется, вызывает события рано.В целом, однако, вы не можете сказать, когда страницы должны переключаться, поэтому в общем случае вы должны также предоставить прослушивателю событий страницу, чтобы убедиться, что она имеет правильную страницу для обработки.