PDF

You are currently browsing articles tagged PDF.

So I’m mixing it up a little bit.  Today’s example prints from a StringBuffer and not a File.  Printing from a File should be pretty similar.  This is useful whenever something needs to be printed out for auditing purposes.

There is some code in here to get around the limitations of a page.  The number of lines on a page and the font size are part of this.  In practice, if the line in the StringBuffer is bigger than the page, it will just disappear.    In this case, the lines were already formatted to be a length that did not skip off of the page.

The code treats the page as a canvas and writes to specific part of that canvas.  If you use this code, be sure to pay attention to all of the settings that inpact the way the text appears on the page.  Some changes will impact other settings.  For example, if the font size is increased, the spacing between lines should increase.

This isn’t particularly object oriented as it is an example.

PrintService printService = PrintHelper.getPrintService(YOUR_PRINTER_NAME);
PrintRequestAttributeSet printRequestAttributeSet = new HashPrintRequestAttributeSet();
printRequestAttributeSet.add(new JobName(YOUR_JOB_NAME,Locale.getDefault()));
PrinterJob pjob = PrinterJob.getPrinterJob();
pjob.setPrintService(printService);

PDDocument document = new PDDocument();
//To load a file do this:   pd = PDDocument.load(input);
PDPage page = new PDPage();
document.addPage( page );
PDFont font = PDType1Font.HELVETICA_BOLD;
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont( font, 12 );
//The first number in moveTextPositionByAmount is to provide a left margin.
//The second number in moveTextPositionByAmount is to miss the header
contentStream.moveTextPositionByAmount( 100, 550 );
StringReader strReader = new StringReader(printText.toString());
BufferedReader strBufRdr = new BufferedReader(strReader);
String line = "";
Integer linesPrinted = 0;
while((line=strBufRdr.readLine()) != null)
{
contentStream.drawString(line);
linesPrinted++;
//The second parameter will change if the font changes.
//It's something that has to be guessed and checked to get right.
contentStream.moveTextPositionByAmount( 0, SPACE BETWEEN LINES -15 SHOULD BE GOOD);
if (linesPrinted % INTEGER_FOR_LINES ON A PAGE 30 SHOULD BE GOOD == 0)
{
contentStream.endText();
contentStream.close();
page = new PDPage();
document.addPage( page );
contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont( font, 12 );
contentStream.moveTextPositionByAmount( 100, 550 );
}
}
contentStream.endText();
contentStream.close();
//For testing, write this to a file
//document.save("outpdf.pdf");
document.silentPrint(pjob);
document.close();
}

catch (PrinterException e)
{
//Handle Error
}
catch (IOException e)
{
//Handle Error
}
}

Tags: , ,

Printing is not an easy task.  It is easy to get tied into intricate details of environment specific configuration settings such as margins and paper size. Therefore, printing a PDF without a library is not recommended unless you have a lot of time or are really interested in that sort of thing.  There are two libraries that can perform this task already.   One will be exampled today, and another tomorrow.

Today’s library is PDFRenderer https://pdf-renderer.dev.java.net/.   This library was released by Sun a couple of years ago.   Note that this example does not map a FileChannel object as some examples do.  Using a FileChannel made the file not able to be deleted until garbage collection was run.  See the bug in the code comments for more details.

try
{
File f = null;
RandomAccessFile fis = null;
FileChannel fc = null;
ByteBuffer bb = null;
String printer = YOUR_PRINTER_NAME;
PrintService printService = PrintHelper.getPrintService(printer);

f = YOUR_PDF_FILE;
//Read only access would work too
fis = new RandomAccessFile(f, "rw");
fc = fis.getChannel();
bb = ByteBuffer.allocate((int)fc.size());
fc.read(bb);


//Do not map the file to a ByteBuffer as the examples show.
// There is a reason why in java bug #474038
// http://bugs.sun.com/view_bug.do?bug_id=4724038
//fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
//bb = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());

PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
PDFPrintPage pages = new PDFPrintPage(pdfFile);
// Create Print Job
PrinterJob pjob = PrinterJob.getPrinterJob();
pjob.setPrintService(printService);

PageFormat pf = PrinterJob.getPrinterJob().defaultPage();

pf.setOrientation(PageFormat.PORTRAIT);

Paper paper = new Paper();

//This is to fix an error in PDF-Renderer
//View http://juixe.com/techknow/index.php/2008/01/17/print-a-pdf-document-in-java/ for details
//Printing a PDF is also possible by sending the bytes directly to the printer, but
//  the printer would have to support it.

paper.setImageableArea(0,0,paper.getWidth() * 2,paper.getHeight());

pf.setPaper(paper);

pjob.setJobName(f.getName());

Book book = new Book();
book.append(pages, pf, pdfFile.getNumPages());
pjob.setPageable(book);
pjob.print();

}
catch (FileNotFoundException e)
{
//do your error action
}
catch (IOException e)
{
//do your error action
}
catch (PrinterException e)
{
//do your error action
}
finally
{
try
{
if (fc != null)
{
fc.close();
fc = null;
}
}
catch (IOException e)
{
log.error(e);
//handle error here
}
try
{
if (fis != null)
{
fis.close();
fis = null;
}
}
catch (IOException e)
{
//handle error here
}
if (bb != null)
{
bb.clear();
}
}

Because this library has the bug that makes it not want to print in half size when printing a portrait-oriented PDF,  I cannot recommend using this library unless you find it is the only thing that will do the job.    Such obvious bugs that have been around for over a year point to unmaintained code or some other upstream issues.  Tune in tomorrow for another library that is maintained that will get the job done as well.

Tags: , ,