Home : Course Map : Chapter 9 : Java : Tech :
I/O for the Histogram Class:
Object Serialization
JavaTech
Course Map
Chapter 9

Introduction
Overview
Streams
Wrappers,Buffers
Console I/O
  Text Output 
     Demo 1

  Formatter/printf()
     Demo 2

  Tex 2t Input
     Demo 3

  Scanner
     
Demo 4
File Class
  File I/O
  File Output-Text
     Demo 5

  Formatter to File
     Demo 6

  File Input - Text
    Demo 7

  Scanner - Files
     Demo 8

  File I/O - Binary
     Demo 9
   Demo 10
File Chooser Dialog
  Demo 11

Character Codes
  Demo 12
   Demo13
Object I/O
Types to Bytes
Stream Filters
Other I/O Topics
Exercises

    Supplements
Character I/O
  Demo 1   Demo 2
Random Access
  Demo 3
ZIP/GZIP Streams
  Demo 4
Piped Streams
  Demo 5
NIO Framework
More NIO
  Demo 6

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

This demonstration program illustrates the use of object serialization to send and receive objects via streams. This means that all of the data that makes up an object is extracted and sent serially to a file or other destination. Conversely, the data can be received and used to rebuild the histogram by creating an instance of the object and placing the data values into their fields.

Serialization is an important aspect of network communications with Java as we will see in Part II. Objects need to be taken apart, sent over the network, and rebuilt at the destination site. Making objects persistent is also an important aspect of object oriented databases.

For a class to work with the ObjectOutputStream and ObjectInputStream classes, it must implement the Serializable interface. This interface has no methods and only serves as a tag to indicate that this class is allowed to be serialized.

The program HistIOSerialApp shown below uses the object serialization techniques to stream a Histogram object to the file. The method writeSerialFile() in the HistIOSerialTools class wraps a ObjectOutputStream around a FileOutputStream object, which in turn streams to a file. The writeObject() method sends the Histogram object onto the stream to the file.

      ObjectOutputStream out =  new ObjectOutputStream (new FileOutputStream (fFile));

      out.writeObject (fHistogram);
      out.flush ();
      out.close ();


Similarly, to read a histogram from a file we can use the method readSerialFile(), which wraps an ObjectInputStream around a FileInputStream object, which in turn streams from a file. The readObject() method obtains the Histogram object from the file:

      FileInputStream in = new FileInputStream (fFile);
      ObjectInputStream oin =  new ObjectInputStream (in);

      Histogram hist = (Histogram) (oin.readObject ());
      oin.close ();

This approach offers an elegant, simple approach to saving and retrieving objects. It has some overhead with regard to managing the bookkeeping for the data values (i.e. knowing what data goes where) and is somewhat slow. Random access to a file full of objects is not provided for.


HistIOSerialApp Application Frame

HistIOSerialApp.java - This application follows closely to the previous HistIOApp example except that it uses the object serialization methods in HistIOTools class to save and read back histogram files.

HistIOSerialTools.java - contains the two static methods shown below. The writeSerialFile(File file, Histogram histogram) method writes a Histogram object to a file with an OutputObjectStream. The method readSerialFile(File file) reads a histogram from such a file using the InputObjectStream.

Histogram.java - For this demo we create a special version of Histogram that is identical to the Chapter 6: Tech Histogram except that it implements the Serializable interface. See below

+ Previous classes:
HstFilter.java - JFileChooser uses this to list ".hst" type files.
Chapter 6:Tech: HistPanel.java
Chapter 6:Tech: PlotPanel.java, PlotFormat.java

/** Special serializable version of Histogram. **/
public class Histogram implements java.io.Serializable {
   ... rest same as the standard Histogram class ...
} // class Histogram

[HistIOSerialTools is the same as HistIOTools discussed in the previous section except for the following two methods.]

  /**
    * Use a ObjectOutputStream wrapped around a FileOutputStream,
    * to write a Histogram  (made Serializable) to the given file.
    *
    * @param file File object for the file to receive the histogram data.
   **/
  public static boolean writeSerialFile (File file,
                                        Histogram histogram) {
    try {
      ObjectOutputStream out =
        new ObjectOutputStream (new FileOutputStream (file));

      out.writeObject (histogram);
      out.flush ();
      out.close ();

    }
    catch (IOException ioe) {
      JOptionPane.showMessageDialog (
                  null,
                  "Error in writing data object!!\n\r"+ioe,
                  "Histogram File Save Error",
                  JOptionPane.ERROR_MESSAGE);
      return false;
    }
    return true;
  } // writeSerialFile

  /**
    *  Use a ObjectInputStream wrapped around a FileInputStream
    *  to read the Histogram object  (made Serializable
    *  from the given file.
    *
    * @param file File object from which to locate file.
   **/
  public static Histogram readSerialFile (File file) {

    try {
      FileInputStream in = new FileInputStream (file);
      ObjectInputStream oin =
           new ObjectInputStream (in);

      Histogram hist =  (Histogram) (oin.readObject ());
      oin.close ();

      return hist;

    }
    catch  (ClassNotFoundException notex) {
      JOptionPane.showMessageDialog (
            null,
            "Error in reading data!!\n\r"+notex,
            "Histogram File Read Error",
            JOptionPane.ERROR_MESSAGE);
      return null;
    }
    catch  (IOException ioe) {
      JOptionPane.showMessageDialog (
            null,
            "Error in reading data!!\n\r"+ioe,
            "Histogram File Read Error",
            JOptionPane.ERROR_MESSAGE);
      return null;
    }
  } // readSerialFile

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

/**
  * Demonstrate streaming I/O by saving and
  * reading in histograms.
**/
public class HistIOSerialApp extends JFrame
       implements ActionListener{
  JMenuItem fMenuOpen;
  JMenuItem fMenuSave;
  JMenuItem fMenuClose;

  // Use the HistPanel JPanel subclass here
  HistPanel fOutputPanel;

  Histogram fHistogram;
  int fNumDataPoints = 100;

  // A text field for input strings
  JTextField fTextField = null;

  //Buttons
  JButton fGoButton;
  JButton fClearButton;

  File fFile;

  /**
    * Pass a title to the frame via the constructor
    * argument.
   **/
  HistIOSerialApp (String title) {
    super (title);
  } // ctor

  /**
    * Create a User Interface with a HistPanel to
    * contain the Histogram object plus buttons to
    * fill and clear the histogram. A text area allows
    * for entry of the number of desired histogram entries.
   **/
  public void init () {

    Container content_pane = getContentPane ();

    // Create a menubar for the frame with File menu
    makeMenuBar ();

    // Now create components for the framed area.
    JPanel panel = new JPanel (new BorderLayout ());

    // Create a histogram with Gaussian distribution.
    makeHist ();

    // JPanel subclass here.
    fOutputPanel = new HistPanel (fHistogram);

    panel.add (fOutputPanel,"Center");

    // Use a textfield for an input parameter.
    fTextField =
      new JTextField (Integer.toString (fNumDataPoints), 10);

    // If return hit after entering text, the
    // actionPerformed will be invoked.
    fTextField.addActionListener (this);

    fGoButton = new JButton ("Go");
    fGoButton.addActionListener (this);

    fClearButton = new JButton ("Clear");
    fClearButton.addActionListener (this);

    JPanel control_panel = new JPanel ();

    control_panel.add (fTextField);
    control_panel.add (fGoButton);
    control_panel.add (fClearButton);

    panel.add (control_panel,"South");

    // Add text area with scrolling to the content pane.
    content_pane.add (panel);

    setSize (400,400);

    setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
  } // init

  /** Create a menu bar with a File drop down menu. **/
  void makeMenuBar () {
    // Use the helper method makeMenuItem
    // for making the menu items and registering
    // their listener.
    JMenu m = new JMenu ("File");

    m.add (fMenuOpen  = makeMenuItem ("Open"));
    m.add (fMenuSave  = makeMenuItem ("Save"));
    m.add (fMenuClose = makeMenuItem ("Quit"));

    JMenuBar mb = new JMenuBar ();
    mb.add (m);
    setJMenuBar (mb);
  } // makeMenuBar

  /** Process the events from the buttons and menu. **/
  public void actionPerformed (ActionEvent e) {
    boolean status = false;
    Object source = e.getSource ();

    // Fill the histogram when the go button clicked or
    // when "enter" hit after a number entered into the
    // textfield
    if (source == fGoButton || source == fTextField) {
      String strNumDataPoints = fTextField.getText ();
      try {
        fNumDataPoints = Integer.parseInt (strNumDataPoints);
      }
      catch (NumberFormatException ex) {
        // Could open an error dialog here but just
        // display a message on the browser status line.
        System.out.println ("Bad input value");
        return;
      }
      // Call the makeHist () method to add data to the histogram.
      // If the first time, it also creates the histogram.
      makeHist ();
      repaint ();
    } else if (source == fClearButton) {
      fHistogram.clear ();
      repaint ();
    }
    // Menu item "Open" for reading in histogram files.
    else if (source == fMenuOpen) {
      // Get a file name with the chooser
      fFile = HistIOSerialTools.openFile (this);
      // Return if no file selected
      if (fFile == null) return;

      Histogram tmpHist = HistIOSerialTools.readSerialFile (fFile);
      if (tmpHist != null)
          fHistogram = tmpHist;
      else {
          JOptionPane.showMessageDialog (
            null,
            "Error opening file!", "File Open Error",
            JOptionPane.ERROR_MESSAGE);
          return;
      }

      // Update panel with new histogram.
      fOutputPanel.setHistogram (fHistogram);
      repaint ();
    }
    // Menu item Save for saving the current histgram
    // to a disk file.
    else if (source == fMenuSave) {
      // Get a file name with the chooser
      fFile = HistIOSerialTools.saveFile (this, null);
      // Return if no file selected
      if (fFile == null) return;

      // Save a file
      status = HistIOSerialTools.writeSerialFile (fFile,fHistogram);
      if (!status)
          JOptionPane.showMessageDialog (
            null,
            "IO error in saving file!!", "File Save Error",
              JOptionPane.ERROR_MESSAGE);
    } else if (source == fMenuClose) {
      dispose ();
    }

  } // actionPerformed


  /** Create a histogram and fill it with Gaussian data. **/
  void makeHist () {
    // Create an instance of the Random class for
    // producing our random values.
    java.util.Random r = new java.util.Random ();

    // Them method nextGaussian in the class Random produces
    // a value centered at 0.0 and a standard deviation
    // of 1.0.

    // Create an instance of our basic histogram class.
    // Make it wide enough enough to include most of the
    // gaussian values.
    if (fHistogram == null)
        fHistogram = new Histogram ("Gaussian Distribution",
                                "random values",
                                20,-3.0,3.0);

    // Fill histogram with Gaussian distribution
    for (int i=0; i < fNumDataPoints; i++) {
        double val = r.nextGaussian ();
        fHistogram.add (val);
    }
  } // makeHist

  /**
    * This "helper method" makes a menu item and then
    * registers this object as a listener to it.
    *
    * @param name menu item label.
   **/
  private JMenuItem makeMenuItem (String name) {
    JMenuItem m = new JMenuItem (name);
    m.addActionListener (this);
    return m;
  } // makeMenuItem

  public static void main (String [] args) {
    // Can pass frame title in command line arguments
    String title="HistIOSerialApp";
      if (args.length != 0) title = args[0];
    HistIOSerialApp f = new HistIOSerialApp (title);
    f.init ();
    f.setVisible (true);
  } // main

} // class HistIOSerialApp

 

References & Web Resources

Latest update: Feb.4.2006

              Tech
Histogram I/O
Hist I/O - Get/Set
  Demo 1
Hist I/O - Objects
  Demo 2
HistogramStream
  Demo 3
Filtering Data
  Demo 4
Exercises

           Physics
Physics Model
Simulation Design
Physics Simulator
  Demo 1
Experiment Design
Experiment Sim.
  Demo 2
Analysis
Expt. + Analysis
  Demo 3
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.