Java/File Input Output/Serialization
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Assists with the serialization process and performs additional functionality based on serialization.
- 2 Computes all the class serialVersionUIDs under the jboss home directory.
- 3 Create a serialized output file
- 4 Object Serialization
- 5 Reconstructing an externalizable object
- 6 Serial Demo
- 7 Serializable
- 8 Serializable Enumeration
- 9 Serialization Utilities
- 10 Serialization with ObjectInputStream and ObjectOutputStream
- 11 Serializer class
- 12 Simple use of Externalizable and a pitfall
- 13 This program shows how to use getSerialVersionUID
- 14 Working with Serialization
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);
}
}
}
}