/*
* 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.com/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;
/**
* A simple class that implements a growable array of ints, and knows how to
* serialize itself as efficiently as a non-growable array.
*/
public class IntList implements Serializable {
protected int[] data = new int[8]; // An array to store the numbers.
protected transient int size = 0; // Index of next unused element of array
/** Return an element of the array */
public int get(int index) throws ArrayIndexOutOfBoundsException {
if (index >= size)
throw new ArrayIndexOutOfBoundsException(index);
else
return data[index];
}
/** Add an int to the array, growing the array if necessary */
public void add(int x) {
if (data.length == size)
resize(data.length * 2); // Grow array if needed.
data[size++] = x; // Store the int in it.
}
/** An internal method to change the allocated size of the array */
protected void resize(int newsize) {
int[] newdata = new int[newsize]; // Create a new array
System.arraycopy(data, 0, newdata, 0, size); // Copy array elements.
data = newdata; // Replace old array
}
/** Get rid of unused array elements before serializing the array */
private void writeObject(ObjectOutputStream out) throws IOException {
if (data.length > size)
resize(size); // Compact the array.
out.defaultWriteObject(); // Then write it out normally.
}
/** Compute the transient size field after deserializing the array */
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject(); // Read the array normally.
size = data.length; // Restore the transient field.
}
/**
* Does this object contain the same values as the object o? We override
* this Object method so we can test the class.
*/
public boolean equals(Object o) {
if (!(o instanceof IntList))
return false;
IntList that = (IntList) o;
if (this.size != that.size)
return false;
for (int i = 0; i < this.size; i++)
if (this.data[i] != that.data[i])
return false;
return true;
}
/** A main() method to prove that it works */
public static void main(String[] args) throws Exception {
IntList list = new IntList();
for (int i = 0; i < 100; i++)
list.add((int) (Math.random() * 40000));
IntList copy = (IntList) Serializer.deepclone(list);
if (list.equals(copy))
System.out.println("equal copies");
Serializer.store(list, new File("intlist.ser"));
}
}
/*
* 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.com/javaexamples2.
*/
/**
* This class defines utility routines that use Java serialization.
*/
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);
}
}
}