I'm using iText library to create and add data to a PDF.
I want to add some textLines and an image to the PDF more than once until i close the file.
numOfSamples = timeIHitTheButton();
.
.
.
*a loop tha call it the number of times choosen by numOfSamples*
DSM.saveData();
The DataStore (DSM is a DataStore instance) class creates the Document doc.pdf correctly and DSM.addText() and DSM.addPicture() prints correctly three textlines an an image on the file, but only if I press the button just once !!
I WANT TO WRITE THE SAME STRING AND AN IMAGE EVERY TIME I PRESS THE BUTTON (if I press it once i have one sample, if trwice i have two samples etc). IF I PRESS IT JUST ONCE AND I TERMINATE, I GET MY PDF WITH THE STRING AND THE PICTURES, BUT IF I PRESS IT MORE THAN ONCE, I GOT AN UNREADABLE AND DAMAGED PDF FILE. I DON'T KNOW WHY. HOW CAN I CONTINUE WRITIN A PICTURE AND THE STRING CONTINUOSLY UNTIL THE NUMBER OF SAMPLES IS FINISHED?
Here i post some code if useful ("newPic1.jpg" "newPic2.jpg" etc are the stored pictures to add to the PDF togheter with the text.):
public class DataStore{ ....
.
.
.
public DataStore(String Str1, String Str2, String Str3, int numOfSemples)
throws Exception{
document = new Document();
String1 = str1;
String2 = str2;
String3 = str3;
Samples = numOfSemples;
document.open();
}
privatevoid saveData(){
if(!created){
this.createFile();
created=true;
}
this.addText();
this.addPicture();
}
private void createFile(){
try {
OutputStream file = new FileOutputStream(
new File("Doc.pdf"));
PdfWriter.getInstance(document, file);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
}
private void addText(){
try {
if(Samples > 0)
document.open();
document.add(new Paragraph(Double.toString(String1)));
document.add(new Paragraph(Double.toString(String2)));
document.add(new Paragraph(Double.toString(String3)));
} catch (DocumentException e) {
e.printStackTrace();
}
}
private void addPicture(){
try {
Image img = Image.getInstance("NewPic" + Samples + ".jpg");
document.add(img);
} catch (BadElementException bee) {
bee.printStackTrace();
} catch (MalformedURLException mue) {
mue.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (DocumentException dee) {
dee.printStackTrace();
}
if(Samples == 0)
document.close();
else Samples--;
}
}
You use iText commands in the wrong order:
DataStore
constructor creates a new Document
and calls its open
method (which is too early as there is no writer yet).saveData
call, you call createFile
which creates the PdfWriter
.saveData
calls addText
is called which for Samples > 0
opens the document again each time (which is ok at the first time but shall not be done multiple times).saveData
call with Samples == 0
you close the document.Thus, in essence you do this:
document = new Document();
document.open();
[...]
PdfWriter.getInstance(document, file);
[...]
[for `Samples` times]
document.open();
[add some paragraphs]
[add an image]
[end for]
document.close();
Compare this to how it should be done:
// step 1
Document document = new Document();
// step 2
PdfWriter.getInstance(document, new FileOutputStream(filename));
// step 3
document.open();
// step 4
[add content to the PDF]
// step 5
document.close();
(copied from the HelloWorld.java sample from iText in Action — 2nd Edition)
Only for Samples == 1
you have it about right (the superfluous document.open()
in the constructor being ignored as there is no writer yet); for larger values of Samples,
though, you open the document multiple times with a writer present which will likely append a PDF start over and over again to the output stream.
Quite likely you can fix the issue by removing all your current document.open()
calls (including the if(Samples > 0)
in addText()
) and add one in createFile()
right after PdfWriter.getInstance(document, file).