Java/File Input Output/Serialization — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
 
м (1 версия)
 
(нет различий)

Текущая версия на 06:02, 1 июня 2010

Assists with the serialization process and performs additional functionality based on serialization.

  
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
/**
 * <p>Assists with the serialization process and performs additional functionality based 
 * on serialization.</p>
 * <p>
 * <ul>
 * <li>Deep clone using serialization
 * <li>Serialize managing finally and IOException
 * <li>Deserialize managing finally and IOException
 * </ul>
 *
 * <p>This class throws exceptions for invalid <code>null</code> inputs.
 * Each method documents its behaviour in more detail.</p>
 *
 * @author 
 * @author Daniel L. Rall
 * @author Stephen Colebourne
 * @author Jeff Varszegi
 * @author Gary Gregory
 * @since 1.0
 * @version $Id: SerializationUtils.java 512889 2007-02-28 18:18:20Z dlr $
 */
public class SerializationUtils {
    
    /**
     * <p>SerializationUtils instances should NOT be constructed in standard programming.
     * Instead, the class should be used as <code>SerializationUtils.clone(object)</code>.</p>
     *
     * <p>This constructor is public to permit tools that require a JavaBean instance
     * to operate.</p>
     * @since 2.0
     */
    public SerializationUtils() {
        super();
    }
    // Clone
    //-----------------------------------------------------------------------
    /**
     * <p>Deep clone an <code>Object</code> using serialization.</p>
     *
     * <p>This is many times slower than writing clone methods by hand
     * on all objects in your object graph. However, for complex object
     * graphs, or for those that don"t support deep cloning this can
     * be a simple alternative implementation. Of course all the objects
     * must be <code>Serializable</code>.</p>
     * 
     * @param object  the <code>Serializable</code> object to clone
     * @return the cloned object
     * @throws SerializationException (runtime) if the serialization fails
     */
    public static Object clone(Serializable object) {
        return deserialize(serialize(object));
    }
    
    // Serialize
    //-----------------------------------------------------------------------
    /**
     * <p>Serializes an <code>Object</code> to the specified stream.</p>
     *
     * <p>The stream will be closed once the object is written.
     * This avoids the need for a finally clause, and maybe also exception
     * handling, in the application code.</p>
     * 
     * <p>The stream passed in is not buffered internally within this method.
     * This is the responsibility of your application if desired.</p>
     *
     * @param obj  the object to serialize to bytes, may be null
     * @param outputStream  the stream to write to, must not be null
     * @throws IllegalArgumentException if <code>outputStream</code> is <code>null</code>
     * @throws SerializationException (runtime) if the serialization fails
     */
    public static void serialize(Serializable obj, OutputStream outputStream) {
        if (outputStream == null) {
            throw new IllegalArgumentException("The OutputStream must not be null");
        }
        ObjectOutputStream out = null;
        try {
            // stream closed in the finally
            out = new ObjectOutputStream(outputStream);
            out.writeObject(obj);
            
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                // ignore close exception
            }
        }
    }
    /**
     * <p>Serializes an <code>Object</code> to a byte array for
     * storage/serialization.</p>
     *
     * @param obj  the object to serialize to bytes
     * @return a byte[] with the converted Serializable
     * @throws SerializationException (runtime) if the serialization fails
     */
    public static byte[] serialize(Serializable obj) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
        serialize(obj, baos);
        return baos.toByteArray();
    }
    // Deserialize
    //-----------------------------------------------------------------------
    /**
     * <p>Deserializes an <code>Object</code> from the specified stream.</p>
     *
     * <p>The stream will be closed once the object is written. This
     * avoids the need for a finally clause, and maybe also exception
     * handling, in the application code.</p>
     * 
     * <p>The stream passed in is not buffered internally within this method.
     * This is the responsibility of your application if desired.</p>
     *
     * @param inputStream  the serialized object input stream, must not be null
     * @return the deserialized object
     * @throws IllegalArgumentException if <code>inputStream</code> is <code>null</code>
     * @throws SerializationException (runtime) if the serialization fails
     */
    public static Object deserialize(InputStream inputStream) {
        if (inputStream == null) {
            throw new IllegalArgumentException("The InputStream must not be null");
        }
        ObjectInputStream in = null;
        try {
            // stream closed in the finally
            in = new ObjectInputStream(inputStream);
            return in.readObject();
            
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(ex);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                // ignore close exception
            }
        }
    }
    /**
     * <p>Deserializes a single <code>Object</code> from an array of bytes.</p>
     *
     * @param objectData  the serialized object, must not be null
     * @return the deserialized object
     * @throws IllegalArgumentException if <code>objectData</code> is <code>null</code>
     * @throws SerializationException (runtime) if the serialization fails
     */
    public static Object deserialize(byte[] objectData) {
        if (objectData == null) {
            throw new IllegalArgumentException("The byte[] must not be null");
        }
        ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
        return deserialize(bais);
    }
    
}





Computes all the class serialVersionUIDs under the jboss home directory.

  
 
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * A tool/service that computes all the class serialVersionUIDs under the jboss
 * home directory.
 * 
 * @author Scott.Stark@jboss.org
 * @author Dimitris.Andreadis@jboss.org
 * @version $Revision: 84164 $
 */
public class SerialVersionUID {
  /** A jdk logger so that only this + ClassVersionInfo are needed */
  static Logger log = Logger.getLogger("SerialVersionUID");
  static void buildJarSet(File dir, HashSet jarFiles) throws MalformedURLException {
    File[] files = dir.listFiles();
    int count = files != null ? files.length : 0;
    System.out.println("Checking dir: " + dir + ", count=" + count);
    for (int n = 0; n < count; n++) {
      File child = files[n];
      // Ignore the server tmp directory
      if (child.isDirectory() && child.getName().equals("tmp") == false)
        buildJarSet(child, jarFiles);
      else if (child.getName().endsWith(".jar"))
        jarFiles.add(child.toURL());
    }
  }
  /**
   * Build a TreeMap of the class name to ClassVersionInfo
   * 
   * @param jar
   * @param classVersionMap
   *          TreeMap<String, ClassVersionInfo> for serializable classes
   * @param cl -
   *          the class loader to use
   * @throws IOException
   *           thrown if the jar cannot be opened
   */
  static void generateJarSerialVersionUIDs(URL jar, TreeMap classVersionMap, ClassLoader cl,
      String pkgPrefix) throws IOException {
    String jarName = jar.getFile();
    JarFile jf = new JarFile(jarName);
    Enumeration entries = jf.entries();
    while (entries.hasMoreElements()) {
      JarEntry entry = (JarEntry) entries.nextElement();
      String name = entry.getName();
      if (name.endsWith(".class") && name.startsWith(pkgPrefix)) {
        name = name.substring(0, name.length() - 6);
        String classname = name.replace("/", ".");
        try {
          log.fine("Creating ClassVersionInfo for: " + classname);
          ClassVersionInfo cvi = new ClassVersionInfo(classname, cl);
          log.fine(cvi.toString());
          if (cvi.getSerialVersion() != 0) {
            ClassVersionInfo prevCVI = (ClassVersionInfo) classVersionMap.put(classname, cvi);
            if (prevCVI != null) {
              if (prevCVI.getSerialVersion() != cvi.getSerialVersion()) {
                log.severe("Found inconsistent classes, " + prevCVI + " != " + cvi + ", jar: "
                    + jarName);
              }
            }
            if (cvi.getHasExplicitSerialVersionUID() == false) {
              log.warning("No explicit serialVersionUID: " + cvi);
            }
          }
        } catch (OutOfMemoryError e) {
          log.log(Level.SEVERE, "Check the MaxPermSize", e);
        } catch (Throwable e) {
          log.log(Level.FINE, "While loading: " + name, e);
        }
      }
    }
    jf.close();
  }
  /**
   * Create a Map<String, ClassVersionInfo> for the jboss dist jars.
   * 
   * @param jbossHome -
   *          the jboss dist root directory
   * @return Map<String, ClassVersionInfo>
   * @throws IOException
   */
  public static Map generateJBossSerialVersionUIDReport(File jbossHome) throws IOException {
    // Obtain the jars from the /lib, common/ and /server/all locations
    HashSet jarFiles = new HashSet();
    File lib = new File(jbossHome, "lib");
    buildJarSet(lib, jarFiles);
    File common = new File(jbossHome, "common");
    buildJarSet(common, jarFiles);
    File all = new File(jbossHome, "server/all");
    buildJarSet(all, jarFiles);
    URL[] cp = new URL[jarFiles.size()];
    jarFiles.toArray(cp);
    ClassLoader parent = Thread.currentThread().getContextClassLoader();
    URLClassLoader completeClasspath = new URLClassLoader(cp, parent);
    TreeMap classVersionMap = new TreeMap();
    Iterator jarIter = jarFiles.iterator();
    while (jarIter.hasNext()) {
      URL jar = (URL) jarIter.next();
      try {
        generateJarSerialVersionUIDs(jar, classVersionMap, completeClasspath, "");
      } catch (IOException e) {
        log.info("Failed to process jar: " + jar);
      }
    }
    return classVersionMap;
  }
  /**
   * Create a Map<String, ClassVersionInfo> for the jboss dist jars.
   * 
   * @param j2eeHome -
   *          the j2ee ri dist root directory
   * @return Map<String, ClassVersionInfo>
   * @throws IOException
   */
  public static Map generateRISerialVersionUIDReport(File j2eeHome) throws IOException {
    // Obtain the jars from the /lib
    HashSet jarFiles = new HashSet();
    File lib = new File(j2eeHome, "lib");
    buildJarSet(lib, jarFiles);
    URL[] cp = new URL[jarFiles.size()];
    jarFiles.toArray(cp);
    ClassLoader parent = Thread.currentThread().getContextClassLoader();
    URLClassLoader completeClasspath = new URLClassLoader(cp, parent);
    TreeMap classVersionMap = new TreeMap();
    Iterator jarIter = jarFiles.iterator();
    while (jarIter.hasNext()) {
      URL jar = (URL) jarIter.next();
      try {
        generateJarSerialVersionUIDs(jar, classVersionMap, completeClasspath, "javax");
      } catch (IOException e) {
        log.info("Failed to process jar: " + jar);
      }
    }
    return classVersionMap;
  }
  /**
   * Generate a mapping of the serial version UIDs for the serializable classes
   * under the jboss dist directory
   * 
   * @param args -
   *          [0] = jboss dist root directory
   * @throws Exception
   */
  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage: jboss-home | -rihome ri-home");
      System.exit(1);
    }
    File distHome = new File(args[0]);
    Map classVersionMap = null;
    if (args.length == 2)
      classVersionMap = generateRISerialVersionUIDReport(distHome);
    else
      classVersionMap = generateJBossSerialVersionUIDReport(distHome);
    // Write the map out the object file
    log.info("Total classes with serialVersionUID != 0: " + classVersionMap.size());
    FileOutputStream fos = new FileOutputStream("serialuid.ser");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(classVersionMap);
    fos.close();
  }
}
/**
 * Encapsulates a class serialVersionUID and codebase.
 * 
 * @author Scott.Stark@jboss.org
 * @version $Revision: 81038 $
 */
class ClassVersionInfo implements Serializable {
  static final long serialVersionUID = 2036506209171911437L;
  /** The named class serialVersionUID as returned by ObjectStreamClass */
  private long serialVersion;
  /** The binary class name */
  private String name;
  private boolean hasExplicitSerialVersionUID;
  private transient URL location;
  public ClassVersionInfo(String name, ClassLoader loader) throws ClassNotFoundException {
    this.name = name;
    Class c = loader.loadClass(name);
    CodeSource cs = c.getProtectionDomain().getCodeSource();
    if (cs != null)
      location = cs.getLocation();
    if (c.isInterface() == false) {
      ObjectStreamClass osc = ObjectStreamClass.lookup(c);
      if (osc != null) {
        serialVersion = osc.getSerialVersionUID();
        try {
          c.getDeclaredField("serialVersionUID");
          hasExplicitSerialVersionUID = true;
        } catch (NoSuchFieldException e) {
          hasExplicitSerialVersionUID = false;
        }
      }
    }
  }
  public long getSerialVersion() {
    return serialVersion;
  }
  public boolean getHasExplicitSerialVersionUID() {
    return hasExplicitSerialVersionUID;
  }
  public String getName() {
    return name;
  }
  public String toString() {
    StringBuffer tmp = new StringBuffer("ClassVersionInfo");
    tmp.append("{");
    tmp.append("serialVersion=");
    tmp.append(serialVersion);
    tmp.append(", hasExplicitSerialVersionUID=");
    tmp.append(hasExplicitSerialVersionUID);
    tmp.append(", name=");
    tmp.append(name);
    tmp.append(", location=");
    tmp.append(location);
    tmp.append("}");
    return tmp.toString();
  }
  /**
   * Usage: ClassVersionInfo class-name
   * 
   * Locate the class name on the thread context class loader classpath and
   * print its version info.
   * 
   * @param args
   *          [0] = class-name
   */
  public static void main(String[] args) throws Exception {
    if (args.length == 0)
      throw new IllegalStateException("Usage: ...ClassVersionInfo class-name");
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    ClassVersionInfo info = new ClassVersionInfo(args[0], loader);
    System.out.println(info);
  }
}





Create a serialized output file

   
// : c12:FreezeAlien.java
// Create a serialized output file.
// {Clean: X.file}
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.io.FileOutputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class FreezeAlien {
  // Throw exceptions to console:
  public static void main(String[] args) throws Exception {
    ObjectOutput out = new ObjectOutputStream(
        new FileOutputStream("X.file"));
    Alien zorcon = new Alien();
    out.writeObject(zorcon);
  }
} ///:~
class Alien implements Serializable {
} ///:~





Object Serialization

   
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class CardReader {
  public static void main(String[] args) {
    Card3 card = new Card3(12, Card3.SPADES);
    System.out.println("Card to write is: " + card);
    try {
      FileOutputStream out = new FileOutputStream("card.out");
      ObjectOutputStream oos = new ObjectOutputStream(out);
      oos.writeObject(card);
      oos.flush();
    } catch (Exception e) {
      System.out.println("Problem serializing: " + e);
    }
    Card3 acard = null;
    try {
      FileInputStream in = new FileInputStream("card.out");
      ObjectInputStream ois = new ObjectInputStream(in);
      acard = (Card3) (ois.readObject());
    } catch (Exception e) {
      System.out.println("Problem serializing: " + e);
    }
    System.out.println("Card read is: " + acard);
  }
}
class Card3 implements Serializable {
  private int suit = UNASSIGNED;
  private int number = UNASSIGNED;
  public final static int UNASSIGNED = -1;
  public final static int DIAMONDS = 1;
  public final static int CLUBS = 2;
  public final static int HEARTS = 3;
  public final static int SPADES = 4;
  public final static int ACE = 1;
  public final static int KING = 13;
  public Card3(int number, int suit) {
    if (isValidNumber(number)) {
      this.number = number;
    } else {
      //Error
    }
    if (isValidSuit(suit)) {
      this.suit = suit;
    } else {
      //Error
    }
  }
  public int getSuit() {
    return suit;
  }
  public int getNumber() {
    return number;
  }
  public static boolean isValidNumber(int number) {
    if (number >= ACE && number <= KING) {
      return true;
    } else {
      return false;
    }
  }
  public static boolean isValidSuit(int suit) {
    if (suit >= DIAMONDS && suit <= SPADES) {
      return true;
    } else {
      return false;
    }
  }
  public boolean equals(Object obj) {
    if (obj instanceof Card3) {
      Card3 card = (Card3) obj;
      if (card.getNumber() == this.number && card.getSuit() == this.suit) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }
  public int hashCode() {
    return number * suit;
  }
  public String toString() {
    return numberToString(this.number) + " of " + suitToString(this.suit);
  }
  public static String numberToString(int number) {
    String result = "";
    switch (number) {
    case ACE:
      result = "Ace";
      break;
    case 2:
      result = "Two";
      break;
    case 3:
      result = "Three";
      break;
    case 4:
      result = "Four";
      break;
    case 5:
      result = "Five";
      break;
    case 6:
      result = "Six";
      break;
    case 7:
      result = "Seven";
      break;
    case 8:
      result = "Eight";
      break;
    case 9:
      result = "Nine";
      break;
    case 10:
      result = "Ten";
      break;
    case 11:
      result = "Jack";
      break;
    case 12:
      result = "Queen";
      break;
    case KING:
      result = "King";
      break;
    case UNASSIGNED:
      result = "Invalid Number";
      break;
    }
    return result;
  }
  public static String suitToString(int suit) {
    String result = "";
    switch (suit) {
    case DIAMONDS:
      result = "Diamonds";
      break;
    case CLUBS:
      result = "Clubs";
      break;
    case HEARTS:
      result = "Hearts";
      break;
    case SPADES:
      result = "Spades";
      break;
    case UNASSIGNED:
      result = "Invalid Suit";
      break;
    }
    return result;
  }
}





Reconstructing an externalizable object

   
// : c12:Blip3.java
// Reconstructing an externalizable object.
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class Blip3 implements Externalizable {
  private int i;
  private String s; // No initialization
  public Blip3() {
    System.out.println("Blip3 Constructor");
    // s, i not initialized
  }
  public Blip3(String x, int a) {
    System.out.println("Blip3(String x, int a)");
    s = x;
    i = a;
    // s & i initialized only in nondefault constructor.
  }
  public String toString() {
    return s + i;
  }
  public void writeExternal(ObjectOutput out) throws IOException {
    System.out.println("Blip3.writeExternal");
    // You must do this:
    out.writeObject(s);
    out.writeInt(i);
  }
  public void readExternal(ObjectInput in) throws IOException,
      ClassNotFoundException {
    System.out.println("Blip3.readExternal");
    // You must do this:
    s = (String) in.readObject();
    i = in.readInt();
  }
  public static void main(String[] args) throws IOException,
      ClassNotFoundException {
    System.out.println("Constructing objects:");
    Blip3 b3 = new Blip3("A String ", 47);
    System.out.println(b3);
    ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(
        "Blip3.out"));
    System.out.println("Saving object:");
    o.writeObject(b3);
    o.close();
    // Now get it back:
    ObjectInputStream in = new ObjectInputStream(new FileInputStream(
        "Blip3.out"));
    System.out.println("Recovering b3:");
    b3 = (Blip3) in.readObject();
    System.out.println(b3);
  }
} ///:~





Serial Demo

   
/*
Database Programming with JDBC and Java, Second Edition
By George Reese
ISBN: 1-56592-616-1
Publisher: O"Reilly
*/

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
 * Example 6-2.
 */
public class SerialDemo implements Serializable {
  static public void main(String[] args) {
    try {
      { // Save a SerialDemo object with a value of 5.
        FileOutputStream f = new FileOutputStream("/tmp/testing");
        ObjectOutputStream s = new ObjectOutputStream(f);
        SerialDemo d = new SerialDemo(5);
        s.writeObject(d);
        s.flush();
      }
      { // Now restore it and look at the value.
        FileInputStream f = new FileInputStream("/tmp/testing");
        ObjectInputStream s = new ObjectInputStream(f);
        SerialDemo d = (SerialDemo) s.readObject();
        System.out.println("SerialDemo.getVal() is: " + d.getVal());
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  int test_val = 7; // value defaults to 7
  public SerialDemo() {
    super();
  }
  public SerialDemo(int x) {
    super();
    test_val = x;
  }
  public int getVal() {
    return test_val;
  }
}





Serializable

   
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
/** Demo of a data class that will be used as a JavaBean or as a data
 * class in a Servlet container; making it Serializable allows
 * it to be saved ("serialized") to disk or over a network connection.
 */
public class SerializableUser implements java.io.Serializable {
  public String name;
  public String address;
  public String country;
  public String phoneNum;
  // other fields, and methods, here...
    static final long serialVersionUID = -7978489268769667877L;
}





Serializable Enumeration

  
/*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.NoSuchElementException;
/**
 * ???
 *      
 * @author ???
 * @version $Revision: 2800 $
 */
@SuppressWarnings("unchecked")
public class SerializableEnumeration
   extends ArrayList
   implements Enumeration
{
   /** The serialVersionUID */
   private static final long serialVersionUID = 8678951571196067510L;
   private int index;
   public SerializableEnumeration () {
      index = 0;
   }
   public SerializableEnumeration (Collection c) {
      super(c);
      index = 0;
   }
   
   public SerializableEnumeration (int initialCapacity) {
      super(initialCapacity);
      index = 0;
   }
   
   public boolean hasMoreElements() {
      return (index < size());
   }
  
   public Object nextElement() throws NoSuchElementException
   {
      try {
         Object nextObj = get(index);
         index++;
         return nextObj;
      }
      catch (IndexOutOfBoundsException e) {
         throw new NoSuchElementException();
      }
   }
   private void writeObject(java.io.ObjectOutputStream out)
      throws java.io.IOException
   {
      // the only thing to write is the index field
      out.defaultWriteObject();
   }
   
   private void readObject(java.io.ObjectInputStream in)
      throws java.io.IOException, ClassNotFoundException
   {
      in.defaultReadObject();
   }
}





Serialization Utilities

  

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializationUtils {
    public static byte[] serialize(Object obj) {
        try {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(buffer);
            oos.writeObject(obj);
            oos.close();
            return buffer.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("error writing to byte-array!");
        }
    }
    public static Object deserialize(byte[] bytes)
            throws ClassNotFoundException {
        try {
            ByteArrayInputStream input = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(input);
            return ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("error reading from byte-array!");
        }
    }
    public static Object serializedCopy(Object obj) {
        try {
            return deserialize(serialize(obj));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("this shouldn"t happen");
        }
    }
}





Serialization with ObjectInputStream and ObjectOutputStream

   
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
class Employee implements java.io.Serializable {
  public String name;
  public String address;
  public transient int SSN;
  public int number;
  public void mailCheck() {
    System.out.println("Mailing a check to " + name + " " + address);
  }
}
class SerializeDemo {
  public static void main(String[] args) {
    Employee e = new Employee();
    e.name = "A";
    e.address = "B";
    e.SSN = 11111;
    e.number = 101;
    try {
      FileOutputStream fileOut = new FileOutputStream("employee.ser");
      ObjectOutputStream out = new ObjectOutputStream(fileOut);
      out.writeObject(e);
      out.close();
      fileOut.close();
    } catch (IOException i) {
      i.printStackTrace();
    }
  }
}
class DeserializeDemo {
  public static void main(String[] args) {
    Employee e = null;
    try {
      FileInputStream fileIn = new FileInputStream("employee.ser");
      ObjectInputStream in = new ObjectInputStream(fileIn);
      e = (Employee) in.readObject();
      in.close();
      fileIn.close();
    } catch (IOException i) {
      i.printStackTrace();
      return;
    } catch (ClassNotFoundException c) {
      System.out.println("Employee class not found");
      c.printStackTrace();
      return;
    }
    System.out.println("Name: " + e.name);
    System.out.println("Address: " + e.address);
    System.out.println("SSN: " + e.SSN);
    System.out.println("Number: " + e.number);
  }
}





Serializer class

   
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd 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.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.ru/javaexamples2.
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Serializable;
/**
 * This class defines utility routines that use Java serialization.
 */
public class Serializer {
  /**
   * Serialize the object o (and any Serializable objects it refers to) and
   * store its serialized state in File f.
   */
  static void store(Serializable o, File f) throws IOException {
    ObjectOutputStream out = // The class for serialization
    new ObjectOutputStream(new FileOutputStream(f));
    out.writeObject(o); // This method serializes an object graph
    out.close();
  }
  /**
   * Deserialize the contents of File f and return the resulting object
   */
  static Object load(File f) throws IOException, ClassNotFoundException {
    ObjectInputStream in = // The class for de-serialization
    new ObjectInputStream(new FileInputStream(f));
    return in.readObject(); // This method deserializes an object graph
  }
  /**
   * Use object serialization to make a "deep clone" of the object o. This
   * method serializes o and all objects it refers to, and then deserializes
   * that graph of objects, which means that everything is copied. This
   * differs from the clone() method of an object which is usually implemented
   * to produce a "shallow" clone that copies references to other objects,
   * instead of copying all referenced objects.
   */
  static Object deepclone(final Serializable o) throws IOException,
      ClassNotFoundException {
    // Create a connected pair of "piped" streams.
    // We"ll write bytes to one, and them from the other one.
    final PipedOutputStream pipeout = new PipedOutputStream();
    PipedInputStream pipein = new PipedInputStream(pipeout);
    // Now define an independent thread to serialize the object and write
    // its bytes to the PipedOutputStream
    Thread writer = new Thread() {
      public void run() {
        ObjectOutputStream out = null;
        try {
          out = new ObjectOutputStream(pipeout);
          out.writeObject(o);
        } catch (IOException e) {
        } finally {
          try {
            out.close();
          } catch (Exception e) {
          }
        }
      }
    };
    writer.start(); // Make the thread start serializing and writing
    // Meanwhile, in this thread, read and deserialize from the piped
    // input stream. The resulting object is a deep clone of the original.
    ObjectInputStream in = new ObjectInputStream(pipein);
    return in.readObject();
  }
  /**
   * This is a simple serializable data structure that we use below for
   * testing the methods above
   */
  public static class DataStructure implements Serializable {
    String message;
    int[] data;
    DataStructure other;
    public String toString() {
      String s = message;
      for (int i = 0; i < data.length; i++)
        s += " " + data[i];
      if (other != null)
        s += "\n\t" + other.toString();
      return s;
    }
  }
  /** This class defines a main() method for testing */
  public static class Test {
    public static void main(String[] args) throws IOException,
        ClassNotFoundException {
      // Create a simple object graph
      DataStructure ds = new DataStructure();
      ds.message = "hello world";
      ds.data = new int[] { 1, 2, 3, 4 };
      ds.other = new DataStructure();
      ds.other.message = "nested structure";
      ds.other.data = new int[] { 9, 8, 7 };
      // Display the original object graph
      System.out.println("Original data structure: " + ds);
      // Output it to a file
      File f = new File("datastructure.ser");
      System.out.println("Storing to a file...");
      Serializer.store(ds, f);
      // Read it back from the file, and display it again
      ds = (DataStructure) Serializer.load(f);
      System.out.println("Read from the file: " + ds);
      // Create a deep clone and display that. After making the copy
      // modify the original to prove that the clone is "deep".
      DataStructure ds2 = (DataStructure) Serializer.deepclone(ds);
      ds.other.message = null;
      ds.other.data = null; // Change original
      System.out.println("Deep clone: " + ds2);
    }
  }
}





Simple use of Externalizable and a pitfall

   
// : c12:Blips.java
// Simple use of Externalizable & a pitfall.
// {Clean: Blips.out}
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
class Blip1 implements Externalizable {
  public Blip1() {
    System.out.println("Blip1 Constructor");
  }
  public void writeExternal(ObjectOutput out) throws IOException {
    System.out.println("Blip1.writeExternal");
  }
  public void readExternal(ObjectInput in) throws IOException,
      ClassNotFoundException {
    System.out.println("Blip1.readExternal");
  }
}
class Blip2 implements Externalizable {
  Blip2() {
    System.out.println("Blip2 Constructor");
  }
  public void writeExternal(ObjectOutput out) throws IOException {
    System.out.println("Blip2.writeExternal");
  }
  public void readExternal(ObjectInput in) throws IOException,
      ClassNotFoundException {
    System.out.println("Blip2.readExternal");
  }
}
public class Blips {
  // Throw exceptions to console:
  public static void main(String[] args) throws IOException,
      ClassNotFoundException {
    System.out.println("Constructing objects:");
    Blip1 b1 = new Blip1();
    Blip2 b2 = new Blip2();
    ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(
        "Blips.out"));
    System.out.println("Saving objects:");
    o.writeObject(b1);
    o.writeObject(b2);
    o.close();
    // Now get them back:
    ObjectInputStream in = new ObjectInputStream(new FileInputStream(
        "Blips.out"));
    System.out.println("Recovering b1:");
    b1 = (Blip1) in.readObject();
    // OOPS! Throws an exception:
    //! System.out.println("Recovering b2:");
    //! b2 = (Blip2)in.readObject();
  }
} ///:~





This program shows how to use getSerialVersionUID

   
import java.io.ObjectStreamClass;
/**
 * This program shows how to use getSerialVersionUID for a class that isn"t in a
 * package and thus not findable to the normal "serialver" tool.
 * 
 * @author Ian Darwin, http://www.darwinsys.ru/
 */
public class GetSerVersUID {
  static final String ident = "$Id: GetSerVersUID.java,v 1.5 2004/02/09 03:33:53 ian Exp $";
  public static void main(String[] av) throws Exception {
    // First we construct a Class object for the given class
    Class cl = Class.forName("Candidate");
    // Then an ObjectStreamClass for the given class
    ObjectStreamClass ocl = ObjectStreamClass.lookup(cl);
    // And use the ObjectStreamClass to get the Class"
    // unique SerialVersionUID
    System.out.println("For class " + cl);
    System.out.println("static final long serialVersionUID = "
        + ocl.getSerialVersionUID() + "L;"); // must be long
    // And just for reference...
    System.out.println("(Must range from " + Long.MIN_VALUE + " to "
        + Long.MAX_VALUE + ".)");
  }
}





Working with Serialization

   
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PersisTest extends JFrame implements ActionListener {
  ArrayList displayList = new ArrayList();;
  String pathname;
  JButton clearBtn, saveBtn, restoreBtn, quitBtn;
  public static void main(String args[]) {
    if (args.length == 0) {
      System.err.println("Usage: java PersisTest filename");
      System.exit(-1);
    }
    new PersisTest(args[0]).show();
  }
  public PersisTest(String pathname) {
    super("Save Me");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.pathname = pathname;
    // Build the GUI. Make this object a listener for all actions.
    JPanel pan = new JPanel();
    clearBtn = new JButton("Clear");
    clearBtn.addActionListener(this);
    pan.add(clearBtn);
    saveBtn = new JButton("Save");
    saveBtn.addActionListener(this);
    pan.add(saveBtn);
    restoreBtn = new JButton("Restore");
    restoreBtn.addActionListener(this);
    pan.add(restoreBtn);
    quitBtn = new JButton("Quit");
    quitBtn.addActionListener(this);
    pan.add(quitBtn);
    Container c = getContentPane();
    c.add(pan, BorderLayout.NORTH);
    c.add(new ClickPanel(), BorderLayout.CENTER);
    setSize(350, 200);
  }
  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == clearBtn) {
      // Repaint with an empty display list.
      displayList = new ArrayList();
      repaint();
    } else if (e.getSource() == saveBtn) {
      // Write display list array list to an object output stream.
      try {
        FileOutputStream fos = new FileOutputStream(pathname);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(displayList);
        oos.flush();
        oos.close();
        fos.close();
      } catch (IOException ex) {
        System.err.println("Trouble writing display list array list");
      }
    } else if (e.getSource() == restoreBtn) {
      // Read a new display list array list from an object input stream.
      try {
        FileInputStream fis = new FileInputStream(pathname);
        ObjectInputStream ois = new ObjectInputStream(fis);
        displayList = (ArrayList) (ois.readObject());
        ois.close();
        fis.close();
        repaint();
      } catch (ClassNotFoundException ex) {
        System.err.println("Trouble reading display list array list");
      } catch (IOException ex) {
        System.err.println("Trouble reading display list array list");
      }
    } else if (e.getSource() == quitBtn) {
      System.exit(0);
    }
  }
  class ClickPanel extends JPanel {
    ClickPanel() {
      MouseListener listener = new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
          // Store x and y in display list array list.
          Point p = new Point(e.getX(), e.getY());
          displayList.add(p);
        }
        public void mouseReleased(MouseEvent e) {
          // Store x and y in display list array list, and request
          // repaint.
          Point p = new Point(e.getX(), e.getY());
          displayList.add(p);
          repaint();
        }
      };
      addMouseListener(listener);
    }
    public void paintComponent(Graphics g) {
      // Clear to white.
      g.setColor(Color.white);
      g.fillRect(0, 0, getSize().width, getSize().height);
      // Traverse display list, drawing 1 rect for each 2 points
      // in the array list.
      g.setColor(Color.black);
      int i = 0;
      while (i < displayList.size()) {
        Point p0 = (Point) (displayList.get(i++));
        Point p1 = (Point) (displayList.get(i++));
        int x = Math.min(p0.x, p1.x);
        int y = Math.min(p0.y, p1.y);
        int w = Math.abs(p0.x - p1.x);
        int h = Math.abs(p0.y - p1.y);
        g.drawRect(x, y, w, h);
      }
    }
  }
}