| 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 |