0
votes

I'm generating a PDDocument in Java with code like this...

HashMap<Integer, PDPageContentStream> mPageContentStreamMap = new HashMap<>();
PDDocument doc = new PDDocument();
for (int i = 1; i <= mNumPages; i++) {
        PDPage page = new PDPage(PDRectangle.A4);
        page.setRotation(90);
        PDPageContentStream pageContentStream = new PDPageContentStream(doc, page);
        contentStreamMap.put(i, pageContentStream);
        doc.addPage(page);
    }
}

Then later save and close the document like this...

for (int i : mPageContentStreamMap.keySet()) {
    mPageContentStreamMap.get(i).close();
}

doc.save("test-filename");
doc.close();

This works fine on the first run; however when I run my program multiple times I get the following error

java.io.IOException: Scratch file already closed
at org.apache.pdfbox.io.ScratchFile.checkClosed(ScratchFile.java:390)
at org.apache.pdfbox.io.ScratchFileBuffer.<init>(ScratchFileBuffer.java:78)
at org.apache.pdfbox.io.ScratchFile.createBuffer(ScratchFile.java:403)
at org.apache.pdfbox.cos.COSStream.createOutputStream(COSStream.java:208)
at org.apache.pdfbox.pdmodel.common.PDStream.createOutputStream(PDStream.java:224)
at org.apache.pdfbox.pdmodel.PDPageContentStream.<init>(PDPageContentStream.java:259)
at org.apache.pdfbox.pdmodel.PDPageContentStream.<init>(PDPageContentStream.java:121)

If I re-run my program without the "doc.close();" line, this error goes away, but the output of the PDF is duplicated (i.e. a new PDF is generated, but with the content from the last PDF and the content from the current PDF).

Is there a way to close the stream and create multiple PDFs without running into the scratch file error?

1
"when I run my program multiple times" means what? Which part is repeated? I'm asking because the PageContentStream you created is "bound" to the document. - Tilman Hausherr
@TilmanHausherr I run the program (main generation method with code above) in a while loop that continues to generate PDF's until a user enters an invalid input. If I run the program just once (no while loop), and restart the program it works fine, but I need it in a loop. - Gabe
To further clarify, I create a 'generator' object once and continuously call the 'generate' method on that object in the loop. - Gabe
Let me ask this differently - when is the contentstreammap initialized? From what I see, mPageContentStreamMap.get(i) will get the content streams of old documents if you don't empty it or create it. - Tilman Hausherr
@TilmanHausherr Turns out to be a problem with my code and not PDFBox, sorry for the scare. I had created a singleton object for my drawing logic meaning after the first run, the same objects were reused when they shouldn't've been. - Gabe

1 Answers

2
votes

I had created a singleton object for my drawing logic meaning after the first run, the same objects were reused when they shouldn't've been, because the input (what was being drawn) had changed.