http://www.fjceballos.es
/*
 * Imprimir un documento con una o más páginas.
 */
package javaappimprimir;

/**
 *
 * @author Fco. Javier Ceballos Sierra: http://www.fjceballos.es (FAQ)
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.File;
import java.io.EOFException;
import java.io.IOException;

public class Main implements Printable, ActionListener
{

  // Nombre del fichero con los datos a imprimir
  static String nombreFichero = null;
  static DataInputStream dis = null; // flujo de entrada
  static int siguientePag = PAGE_EXISTS; // hay una página más
  static boolean pagImpresa = false; // ¿págima impresa?
  static Graphics2D g2d = null; // superficie de impresión

  public void actionPerformed(ActionEvent e)
  {
    // Crear un trabajo de impresión
    PrinterJob job = PrinterJob.getPrinterJob();
    // Asignar el objeto pintor: debe implementar la interfaz Printable
    job.setPrintable(this);
    // Mostrar un cuadro de diálogo de impresión para modificar los
    // parámetros de job
    if (job.printDialog())
    {
      try
      {
        job.print(); // llamar al método de impresión
      }
      catch (PrinterException ex)
      {
        System.out.println(ex.getMessage());
      }
    }
  }

  public int print(Graphics g, PageFormat formatoPag, int numPag)
  throws PrinterException
  {
    // ¿Bug?: el método print es llamado dos veces con cada numPag:
    // núm. pag.: 0
    // núm. pag.: 0
    // núm. pag.: 1
    // núm. pag.: 1
    // (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4186108)
    System.out.println("núm. pag.: " + numPag);
    // Solución provisional:
    if (!pagImpresa)
    {
      pagImpresa = true;
      return siguientePag;
    }

    // g <-- g2d: superficie de impresión.
    // formatoPag: formato de la página.
    // numPag: número de página (inicialmente es igual a 0).
    // Establecer la fuente para la superficie de impresión.
    Font font = new Font("Arial", Font.PLAIN, 10);
    FontMetrics metrics = g.getFontMetrics(font);
    // Obtener el alto de la línea que se imprime
    int altoLinea = metrics.getHeight();

    // Establecer márgenes
    double margenIzDe = 0, margenSupInf = 0, anchoPag = 0, altoPag = 0;
    if (numPag == 0)
    {
        margenIzDe = Math.ceil(altoLinea * 3);
        margenSupInf = Math.ceil(altoLinea * 4);
        anchoPag = Math.ceil(formatoPag.getImageableWidth());
        altoPag = Math.ceil(formatoPag.getImageableHeight());

        Paper papel = formatoPag.getPaper();
        papel.setImageableArea(margenIzDe, margenSupInf,
                               anchoPag - 2*margenIzDe, altoPag - 3*margenSupInf);
        formatoPag.setPaper(papel);
    }

    // Utilizaremos la clase Graphics2D derivada de Graphics que proporciona
    // más funcionalidad.
    // Establecer el origen (0,0) de impresión para la página actual:
    g2d = (Graphics2D) g;
    g2d.translate(formatoPag.getImageableX(), formatoPag.getImageableY());

    // Línea a imprimir.
    String linea = "";
    int y = altoLinea;
    altoPag = Math.ceil(formatoPag.getImageableHeight()); // alto actual

    while (siguientePag == PAGE_EXISTS && y < altoPag+margenIzDe)
    {
      linea = leerUnRegistro(); // devuelve null si fin de fichero.
      if (linea == null)
      {
        siguientePag = NO_SUCH_PAGE; // no hay más páginas
        break;
      }

      g.drawString(linea, 0, y); // pintar la línea.
      y += altoLinea;            // coordenada "y" de la siguiente línea
      System.out.println("linea: " + linea + " - y: " + y + ", alto: " + altoPag);
    }
    pagImpresa = false; // iniciar para la siguiente página
    return siguientePag; // siguiente página
  }

  public String leerUnRegistro()
  {
    //Declarar los datos a leer desde el fichero
    String nombre, direccion;
    long telefono;
    String cadena = null;
    try
    {
      // Leer un nombre, una direccion y un teléfono desde el
      // fichero. Cuando se alcance el final del fichero Java
      // lanzará una excepción del tipo EOFException
      nombre = dis.readUTF();
      direccion = dis.readUTF();
      telefono = dis.readLong();
      cadena = nombre + ",  " + direccion + ",  tfno.: " + telefono;
    }
    catch (EOFException e)
    {
      System.out.println("Fin del fichero.");
      cadena = null;
    }
    catch (IOException e)
    {
      System.out.println("Error de lectura.");
      System.exit(0);
    }

    return cadena;
  }

  public static void main(String args[])
  {
    File fichero = null;
    nombreFichero = "agenda.dat"; // está en la carpeta de la aplicación
    fichero = new File(nombreFichero);
    if (!fichero.exists())
    {
      System.out.print("El archivo no existe...");
      return;
    }
    // Permitir el acceso al fichero
    try
    {
      // Crear un flujo para leer
      dis = new DataInputStream(new BufferedInputStream(
                                new FileInputStream(nombreFichero)));
    }
    catch (IOException e)
    {
      System.out.println(e.getMessage());
    }

    // Crear una ventana
    JFrame f = new JFrame("Imprimir desde Java (http://www.fjceballos.es)");
    f.addWindowListener(new WindowAdapter()
    {
      @Override
      public void windowClosing(WindowEvent e)
      {
        // Cerar el flujo
        if (dis != null)
        {
          try { dis.close(); } catch (IOException ex) {}
        }
        System.exit(0);
      }
    });
    JButton printButton = new JButton("Imprimir");
    printButton.addActionListener(new Main());
    f.add("Center", printButton);
    f.setSize(400, 300);
    f.setVisible(true);
  }
}