File Input Output Java

/*
 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit http://www.davidflanagan.com/javaexamples3.
 */
//package je3.print;
import java.awt.Button;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.PrintJob;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.TimeZone;
/**
 * A character output stream that sends output to a printer.
 */
public class HardcopyWriter extends Writer {
  // These are the instance variables for the class
  protected PrintJob job; // The PrintJob object in use
  protected Graphics page; // Graphics object for current page
  protected String jobname; // The name of the print job
  protected int fontsize; // Point size of the font
  protected String time; // Current time (appears in header)
  protected Dimension pagesize; // Size of the page (in dots)
  protected int pagedpi; // Page resolution in dots per inch
  protected Font font, headerfont; // Body font and header font
  protected FontMetrics metrics; // Metrics for the body font
  protected FontMetrics headermetrics; // Metrics for the header font
  protected int x0, y0; // Upper-left corner inside margin
  protected int width, height; // Size (in dots) inside margins
  protected int headery; // Baseline of the page header
  protected int charwidth; // The width of each character
  protected int lineheight; // The height of each line
  protected int lineascent; // Offset of font baseline
  protected int chars_per_line; // Number of characters per line
  protected int lines_per_page; // Number of lines per page
  protected int charnum = 0, linenum = 0; // Current column and line position
  protected int pagenum = 0; // Current page number
  // A field to save state between invocations of the write() method
  private boolean last_char_was_return = false;
  // A static variable that holds user preferences between print jobs
  protected static Properties printprops = new Properties();
  /**
   * The constructor for this class has a bunch of arguments: The frame argument
   * is required for all printing in Java. The jobname appears left justified at
   * the top of each printed page. The font size is specified in points, as
   * on-screen font sizes are. The margins are specified in inches (or fractions
   * of inches).
   */
  public HardcopyWriter(Frame frame, String jobname, int fontsize, double leftmargin,
      double rightmargin, double topmargin, double bottommargin)
      throws HardcopyWriter.PrintCanceledException {
    // Get the PrintJob object with which we'll do all the printing.
    // The call is synchronized on the static printprops object, which
    // means that only one print dialog can be popped up at a time.
    // If the user clicks Cancel in the print dialog, throw an exception.
    Toolkit toolkit = frame.getToolkit(); // get Toolkit from Frame
    synchronized (printprops) {
      job = toolkit.getPrintJob(frame, jobname, printprops);
    }
    if (job == null)
      throw new PrintCanceledException("User cancelled print request");
    pagesize = job.getPageDimension(); // query the page size
    pagedpi = job.getPageResolution(); // query the page resolution
    // Bug Workaround:
    // On windows, getPageDimension() and getPageResolution don't work, so
    // we've got to fake them.
    if (System.getProperty("os.name").regionMatches(true, 0, "windows", 0, 7)) {
      // Use screen dpi, which is what the PrintJob tries to emulate
      pagedpi = toolkit.getScreenResolution();
      // Assume a 8.5" x 11" page size. A4 paper users must change this.
      pagesize = new Dimension((int) (8.5 * pagedpi), 11 * pagedpi);
      // We also have to adjust the fontsize. It is specified in points,
      // (1 point = 1/72 of an inch) but Windows measures it in pixels.
      fontsize = fontsize * pagedpi / 72;
    }
    // Compute coordinates of the upper-left corner of the page.
    // I.e. the coordinates of (leftmargin, topmargin). Also compute
    // the width and height inside of the margins.
    x0 = (int) (leftmargin * pagedpi);
    y0 = (int) (topmargin * pagedpi);
    width = pagesize.width - (int) ((leftmargin + rightmargin) * pagedpi);
    height = pagesize.height - (int) ((topmargin + bottommargin) * pagedpi);
    // Get body font and font size
    font = new Font("Monospaced", Font.PLAIN, fontsize);
    metrics = frame.getFontMetrics(font);
    lineheight = metrics.getHeight();
    lineascent = metrics.getAscent();
    charwidth = metrics.charWidth('0'); // Assumes a monospaced font!
    // Now compute columns and lines will fit inside the margins
    chars_per_line = width / charwidth;
    lines_per_page = height / lineheight;
    // Get header font information
    // And compute baseline of page header: 1/8" above the top margin
    headerfont = new Font("SansSerif", Font.ITALIC, fontsize);
    headermetrics = frame.getFontMetrics(headerfont);
    headery = y0 - (int) (0.125 * pagedpi) - headermetrics.getHeight() + headermetrics.getAscent();
    // Compute the date/time string to display in the page header
    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
    df.setTimeZone(TimeZone.getDefault());
    time = df.format(new Date());
    this.jobname = jobname; // save name
    this.fontsize = fontsize; // save font size
  }
  /**
   * This is the write() method of the stream. All Writer subclasses implement
   * this. All other versions of write() are variants of this one
   */
  public void write(char[] buffer, int index, int len) {
    synchronized (this.lock) { // For thread safety
      // Loop through all the characters passed to us
      for (int i = index; i < index + len; i++) {
        // If we haven't begun a page (or a new page), do that now.
        if (page == null)
          newpage();
        // If the character is a line terminator, then begin new line,
        // unless it is a \n immediately after a \r.
        if (buffer[i] == '\n') {
          if (!last_char_was_return)
            newline();
          continue;
        }
        if (buffer[i] == '\r') {
          newline();
          last_char_was_return = true;
          continue;
        } else
          last_char_was_return = false;
        // If it some other non-printing character, ignore it.
        if (Character.isWhitespace(buffer[i]) && !Character.isSpaceChar(buffer[i])
            && (buffer[i] != '\t'))
          continue;
        // If no more characters will fit on the line, start new line.
        if (charnum >= chars_per_line) {
          newline();
          // Also start a new page, if necessary
          if (page == null)
            newpage();
        }
        // Now print the character:
        // If it is a space, skip one space, without output.
        // If it is a tab, skip the necessary number of spaces.
        // Otherwise, print the character.
        // It is inefficient to draw only one character at a time, but
        // because our FontMetrics don't match up exactly to what the
        // printer uses we need to position each character individually
        if (Character.isSpaceChar(buffer[i]))
          charnum++;
        else if (buffer[i] == '\t')
          charnum += 8 - (charnum % 8);
        else {
          page.drawChars(buffer, i, 1, x0 + charnum * charwidth, y0 + (linenum * lineheight)
              + lineascent);
          charnum++;
        }
      }
    }
  }
  /**
   * This is the flush() method that all Writer subclasses must implement. There
   * is no way to flush a PrintJob without prematurely printing the page, so we
   * don't do anything.
   */
  public void flush() { /* do nothing */
  }
  /**
   * This is the close() method that all Writer subclasses must implement. Print
   * the pending page (if any) and terminate the PrintJob.
   */
  public void close() {
    synchronized (this.lock) {
      if (page != null)
        page.dispose(); // Send page to the printer
      job.end(); // Terminate the job
    }
  }
  /**
   * Set the font style. The argument should be one of the font style constants
   * defined by the java.awt.Font class. All subsequent output will be in that
   * style. This method relies on all styles of the Monospaced font having the
   * same metrics.
   */
  public void setFontStyle(int style) {
    synchronized (this.lock) {
      // Try to set a new font, but restore current one if it fails
      Font current = font;
      try {
        font = new Font("Monospaced", style, fontsize);
      } catch (Exception e) {
        font = current;
      }
      // If a page is pending, set the new font. Otherwise newpage() will
      if (page != null)
        page.setFont(font);
    }
  }
  /** End the current page. Subsequent output will be on a new page. */
  public void pageBreak() {
    synchronized (this.lock) {
      newpage();
    }
  }
  /** Return the number of columns of characters that fit on the page */
  public int getCharactersPerLine() {
    return this.chars_per_line;
  }
  /** Return the number of lines that fit on a page */
  public int getLinesPerPage() {
    return this.lines_per_page;
  }
  /** This internal method begins a new line */
  protected void newline() {
    charnum = 0; // Reset character number to 0
    linenum++; // Increment line number
    if (linenum >= lines_per_page) { // If we've reached the end of page
      page.dispose(); // send page to printer
      page = null; // but don't start a new page yet.
    }
  }
  /** This internal method begins a new page and prints the header. */
  protected void newpage() {
    page = job.getGraphics(); // Begin the new page
    linenum = 0;
    charnum = 0; // Reset line and char number
    pagenum++; // Increment page number
    page.setFont(headerfont); // Set the header font.
    page.drawString(jobname, x0, headery); // Print job name left justified
    String s = "- " + pagenum + " -"; // Print the page # centered.
    int w = headermetrics.stringWidth(s);
    page.drawString(s, x0 + (this.width - w) / 2, headery);
    w = headermetrics.stringWidth(time); // Print date right justified
    page.drawString(time, x0 + width - w, headery);
    // Draw a line beneath the header
    int y = headery + headermetrics.getDescent() + 1;
    page.drawLine(x0, y, x0 + width, y);
    // Set the basic monospaced font for the rest of the page.
    page.setFont(font);
  }
  /**
   * This is the exception class that the HardcopyWriter constructor throws when
   * the user clicks "Cancel" in the print dialog box.
   */
  public static class PrintCanceledException extends Exception {
    public PrintCanceledException(String msg) {
      super(msg);
    }
  }
  /**
   * A program that prints the specified file using HardcopyWriter
   */
  public static class PrintFile {
    public static void main(String[] args) {
      try {
        if (args.length != 1)
          throw new IllegalArgumentException("Wrong # of arguments");
        FileReader in = new FileReader(args[0]);
        HardcopyWriter out = null;
        Frame f = new Frame("PrintFile: " + args[0]);
        f.setSize(200, 50);
        f.show();
        try {
          out = new HardcopyWriter(f, args[0], 10, .5, .5, .5, .5);
        } catch (HardcopyWriter.PrintCanceledException e) {
          System.exit(0);
        }
        f.setVisible(false);
        char[] buffer = new char[4096];
        int numchars;
        while ((numchars = in.read(buffer)) != -1)
          out.write(buffer, 0, numchars);
        in.close();
        out.close();
      } catch (Exception e) {
        System.err.println(e);
        System.err.println("Usage: " + "java HardcopyWriter$PrintFile ");
        System.exit(1);
      }
      System.exit(0);
    }
  }
  /**
   * A program that prints a demo page using HardcopyWriter
   */
  public static class Demo extends Frame implements ActionListener {
    /** The main method of the program. Create a test window */
    public static void main(String[] args) {
      Frame f = new Demo();
      f.show();
    }
    // Buttons used in this program
    protected Button print, quit;
    /** Constructor for the test program's window. */
    public Demo() {
      super("HardcopyWriter Test"); // Call frame constructor
      Panel p = new Panel(); // Add a panel to the frame
      this.add(p, "Center"); // Center it
      p.setFont(new Font("SansSerif", // Set a default font
          Font.BOLD, 18));
      print = new Button("Print Test Page"); // Create a Print button
      quit = new Button("Quit"); // Create a Quit button
      print.addActionListener(this); // Specify that we'll handle
      quit.addActionListener(this); // button presses
      p.add(print); // Add the buttons to panel
      p.add(quit);
      this.pack(); // Set the frame size
    }
    /** Handle the button presses */
    public void actionPerformed(ActionEvent e) {
      Object o = e.getSource();
      if (o == quit)
        System.exit(0);
      else if (o == print)
        printDemoPage();
    }
    /** Print the demo page */
    public void printDemoPage() {
      // Create a HardcopyWriter, using a 10 point font and 3/4" margins.
      HardcopyWriter hw;
      try {
        hw = new HardcopyWriter(this, "Demo Page", 10, .75, .75, .75, .75);
      } catch (HardcopyWriter.PrintCanceledException e) {
        return;
      }
      // Send output to it through a PrintWriter stream
      PrintWriter out = new PrintWriter(hw);
      // Figure out the size of the page
      int rows = hw.getLinesPerPage(), cols = hw.getCharactersPerLine();
      // Mark upper left and upper-right corners
      out.print("+"); // upper-left corner
      for (int i = 0; i < cols - 2; i++)
        out.print(" "); // space over
      out.print("+"); // upper-right corner
      // Display a title
      hw.setFontStyle(Font.BOLD + Font.ITALIC);
      out.println("\n\t\tHardcopy Writer Demo Page\n\n");
      // Demonstrate font styles
      hw.setFontStyle(Font.BOLD);
      out.println("Font Styles:");
      int[] styles = { Font.PLAIN, Font.BOLD, Font.ITALIC, Font.ITALIC + Font.BOLD };
      for (int i = 0; i < styles.length; i++) {
        hw.setFontStyle(styles[i]);
        out.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz");
        out.println("1234567890!@#$%^&*()[]{}<>,.?:;+-=/\\`'\"_~|");
      }
      hw.setFontStyle(Font.PLAIN);
      out.println("\n");
      // Demonstrate tab stops
      hw.setFontStyle(Font.BOLD);
      out.println("Tab Stops:");
      hw.setFontStyle(Font.PLAIN);
      out.println("          1         2         3         4         5");
      out.println("012345678901234567890123456789012345678901234567890");
      out.println("^\t^\t^\t^\t^\t^\t^");
      out.println("\n");
      // Output some information about page dimensions and resolution
      hw.setFontStyle(Font.BOLD);
      out.println("Dimensions:");
      hw.setFontStyle(Font.PLAIN);
      out.println("\tResolution: " + hw.pagedpi + " dots per inch");
      out.println("\tPage width (pixels): " + hw.pagesize.width);
      out.println("\tPage height (pixels): " + hw.pagesize.height);
      out.println("\tWidth inside margins (pixels): " + hw.width);
      out.println("\tHeight inside margins (pixels): " + hw.height);
      out.println("\tCharacters per line: " + cols);
      out.println("\tLines per page: " + rows);
      // Skip down to the bottom of the page
      for (int i = 0; i < rows - 30; i++)
        out.println();
      // And mark the lower left and lower right
      out.print("+"); // lower-left
      for (int i = 0; i < cols - 2; i++)
        out.print(" "); // space-over
      out.print("+"); // lower-right
      // Close the output stream, forcing the page to be printed
      out.close();
    }
  }
}