Print Text File to Specific Windows Printer in Java with wrap-around and multi-page

Posted on 2014-12-14
Last Modified: 2015-01-17
I am trying to print a text file to a specific Windows printer. All I need to consider, that if the particular
line doesn't print within the margins of the page than wrapping it around to the next line starting with
non-broken "words", meaning that break the line only on space characters
and if a single printed page will not be sufficient to print out the full file it would be printed
on more than one pages.

As far a simple example for printing text files, this is all I could find, but this is for printing single pages
with truncated lines:

Based on this, this is my code:

The main class,

import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JOptionPane;

public class Printer_Test {
    public static void main(String[] args) {
        ArrayList<String> listFileContents = new ArrayList<String>();
               try {
                   // Get the latest file in folder,  Open the file:
                   FileInputStream fstream = new FileInputStream("input.txt");
                   // Get the object of DataInputStream
                   DataInputStream in = new DataInputStream(fstream);
                   BufferedReader br = new BufferedReader(new InputStreamReader(in));
                   String strLine;
                   //Read File Line By Line
                   while ((strLine = br.readLine()) != null) {
                   //Close the input stream
               } catch (Exception e) {
                   System.err.println("Error: " + e.getMessage());
                   JOptionPane.showMessageDialog(null, e.getMessage(), "File I/O Error", JOptionPane.ERROR_MESSAGE);
    }  // End of main()
// Print to printer method uses OutputPrinter class
// it will print the contents of jtxtAreaDiagnostic text area
               private static void printToPrinter(ArrayList<String> listOfFileContents) {
                   // Calling a method for getting all diag info out of jlstDiagnostic loaded contents:

                   // Make a String out of the Arraylist<String>:
                   String printData = "";
                   Iterator it =  listOfFileContents.iterator();
                   while (it.hasNext()) {
                       printData = printData +;
                       printData = printData + "\r\n";

                   // Feed the data to be printed to the PrinterJob instance:
                   PrinterJob job = PrinterJob.getPrinterJob();
                   job.setPrintable(new OutputPrinter(printData));
                   boolean doPrint = job.printDialog();
                   if (doPrint) {
                       try {
                       } catch (PrinterException e) {
                           // Print job did not complete.

Open in new window

The other class OutputPrinter implements Printable:

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;

public class OutputPrinter implements Printable {
    private String printData;

    public OutputPrinter(String printDataIn) {
        this.printData = printDataIn;

    public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
        // Should only have one page, and page # is zero-based.
        if (page > 0) {
            return NO_SUCH_PAGE;

        // Adding the "Imageable" to the x and y puts the margins on the page.
        // To make it safe for printing.
        Graphics2D g2d = (Graphics2D) g;
        int x = (int) pf.getImageableX();
        int y = (int) pf.getImageableY();
        g2d.translate(x, y);

        // Calculate the line height
        Font font = new Font("Serif", Font.PLAIN, 10);
        FontMetrics metrics = g.getFontMetrics(font);
        int lineHeight = metrics.getHeight();

        BufferedReader br = new BufferedReader(new StringReader(printData));

        // Draw the page:
        try {
            String line;
            // Just a safety net in case no margin was added.
            x += 50;
            y += 50;
            while ((line = br.readLine()) != null) {
                y += lineHeight;
                g2d.drawString(line, x, y);
        } catch (IOException e) {
        return PAGE_EXISTS;

Open in new window

How can you modify this to make it multi-page, and to wrap around to the next line when the last word
is reached de-limited with a white space from the next word that will not fit?

Nothing seems to work for me.
Any suggestions / good examples for Java text printing to Windows printer practically?
Question by:AttilaB
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2

Accepted Solution

AttilaB earned 0 total points
ID: 40510333
Well, I came up with something that is almost a solution -  Pageable and Printable both need to be implemented:

I based this off the following examples:,double%20y,double%20width,double%20height%29.html

BUT! The user cannot set the orientation or paper size manually. Actually he / she can, but it will be printed Letter size and Landscape orientation anyhow. I wonder why.

The code:

1. The driver class with main() method:

import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;

public class PageableText_Main {

    public static void main(String[] args) {
        // Get the PrinterJob object that coordinates everything about printing:
        PrinterJob job = PrinterJob.getPrinterJob();

        // Get the page format:
        PageFormat format = definePageFormat(job);
        // Default attributes to printer:
        PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();

        // Create our PageableText object, and tell the PrinterJob about it
        try {
            job.setPageable(new PageableText(new File("input.txt"), format));
        } catch (IOException ex) {
            System.out.println("Cannot load file to print");

        // Ask the user to select a printer, etc., and if not canceled, print pages:
        try {
            if (job.printDialog(attributes))
        } catch (PrinterException e) {
            System.out.println("Cannot Select Printer");

    private static PageFormat definePageFormat(PrinterJob printJob) {
        PageFormat pageFormat = printJob.defaultPage();
        Paper paper = pageFormat.getPaper();
        paper.setSize(8.5 * 72, 11 * 72);
        paper.setImageableArea(0.875 * 72, 0.625 * 72, 6.75 * 72, 9.75 * 72);
        return pageFormat;

Open in new window

And this is the PageableText class implements Pageable, Printable interfaces:

import java.awt.*;
import java.awt.print.*;
import java.util.Vector;

public class PageableText implements Pageable, Printable {
    // Constants for font name, size, style and line spacing
    public static String FONTFAMILY = "Monospaced";
    public static int FONTSIZE = 10;
    public static int FONTSTYLE = Font.PLAIN;
    public static float LINESPACEFACTOR = 1.1f;

    PageFormat format; // The page size, margins, and orientation
    Vector lines; // The text to be printed, broken into lines
    Font font; // The font to print with
    int linespacing; // How much space between lines
    int linesPerPage; // How many lines fit on a page
    int numPages; // How many pages required to print all lines
    int baseline = -1; // The baseline position of the font.

    /** Create a PageableText object for a string of text */
    public PageableText(String text, PageFormat format) throws IOException {
        this(new StringReader(text), format);

    /** Create a PageableText object for a file of text */
    public PageableText(File file, PageFormat format) throws IOException {
        this(new FileReader(file), format);

    /** Create a PageableText object for a stream of text */
    public PageableText(Reader stream, PageFormat format) throws IOException {
        this.format = format;

        // First, read all the text, breaking it into lines.
        // This code ignores tabs, and does not wrap long lines.
        BufferedReader in = new BufferedReader(stream);
        lines = new Vector();
        String line;
        while ((line = in.readLine()) != null)

        // Create the font we will use, and compute spacing between lines
        font = new Font(FONTFAMILY, FONTSTYLE, FONTSIZE);
        linespacing = (int) (FONTSIZE * LINESPACEFACTOR);

        // Figure out how many lines per page, and how many pages
        linesPerPage = (int) Math.floor(format.getImageableHeight() / linespacing);
        numPages = (lines.size() - 1) / linesPerPage + 1;

    // These are the methods of the Pageable interface.
    // Note that the getPrintable() method returns this object, which means
    // that this class must also implement the Printable interface.
    public int getNumberOfPages() {
        return numPages;

    public PageFormat getPageFormat(int pagenum) {
        return format;

    public Printable getPrintable(int pagenum) {
        return this;

     * This is the print() method of the Printable interface.
     * It does most of the printing work.
    public int print(Graphics g, PageFormat format, int pagenum) {
        // Tell the PrinterJob if the page number is not a legal one.
        if ((pagenum < 0) | (pagenum >= numPages))
            return NO_SUCH_PAGE;

        // First time we're called, figure out the baseline for our font.
        // We couldn't do this earlier because we needed a Graphics object
        if (baseline == -1) {
            FontMetrics fm = g.getFontMetrics(font);
            baseline = fm.getAscent();

        // Clear the background to white.  This shouldn't be necessary, but is
        // required on some systems to workaround an implementation bug
        g.fillRect((int) format.getImageableX(), (int) format.getImageableY(), (int) format.getImageableWidth(),
                   (int) format.getImageableHeight());

        // Set the font and the color we will be drawing with.
        // Note that you cannot assume that black is the default color!

        // Figure out which lines of text we will print on this page
        int startLine = pagenum * linesPerPage;
        int endLine = startLine + linesPerPage - 1;
        if (endLine >= lines.size())
            endLine = lines.size() - 1;

        // Compute the position on the page of the first line.
        int x0 = (int) format.getImageableX();
        int y0 = (int) format.getImageableY() + baseline;

        // Loop through the lines, drawing them all to the page.
        for (int i = startLine; i <= endLine; i++) {
            // Get the line
            String line = (String) lines.elementAt(i);

            // Draw the line.
            // We use the integer version of drawString(), not the Java 2D
            // version that uses floating-point coordinates. A bug in early
            // Java2 implementations prevents the Java 2D version from working.
            if (line.length() > 0)
                g.drawString(line, x0, y0);

            // Move down the page for the next line.
            y0 += linespacing;

        // Tell the PrinterJob that we successfully printed the page.
        return PAGE_EXISTS;

Open in new window


Author Comment

ID: 40546441
I agree The question should be closed.
LVL 38

Expert Comment

ID: 40554984
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.

Featured Post

Save the day with this special offer from ATEN!

Save 30% on the CV211 using promo code EXPERTS30 now through April 30th. The ATEN CV211 connects a laptop directly to any server allowing you instant access to perform data maintenance and local operations, for quick troubleshooting, updating, service and repair.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

How to solve seemingly unsolvable printer issues. Users sometimes run into printing issues where all the normal steps do not seem to work. Well the steps below can show users how to take one extra step beyond the normal steps needed to remove old…
This seems to be a very common error related to the Samsung printer driver. First, this is the error we're talking about: Log: System Type: Error Event: 7000 Agent Time: 3:37:24 am 22-Apr-09 Event Time: 6:07:24 pm 21-Apr-09 UTC Source: Se…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
In an interesting question ( here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

695 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question