|
| |
Java's serialization mechanism provides a mechanism for
classes to specify how they wish the serialization to
proceed. You can:
- supplement the default serialization, or
- override it entirely
You can specify that a class perform custom serialization
by defining methods with the signatures:
private void writeObject(ObjectOutputStream out)
throws IOException
and:
private void readObject(ObjectInputStream in)
throws IOException,
ClassNotFoundException
Note:
These methods must be declared private, and are not
declared in any interface (interfaces can only
declare public methods).
If you wish to supplement the default serialization, you
must ensure that when you implement these methods, they call
the default serialization methods:
private void writeObject(ObjectOutputStream out)
throws IOException
{
// ...
out.defaultWriteObject();
// ...
}
private void readObject(ObjectInputStream in)
throws IOException,
ClassNotFoundException
{
// ...
in.defaultReadObject();
// ...
}
So let's modify the RecordedPerson
class to augment the default serialization on input:
package serialization;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
public class RecordedPerson
extends Person
{
// Constructor to create a recorded person and
// the associated record file
public RecordedPerson(String name, int age, int id)
{
super(name, age);
m_id = id;
createRecordFile();
}
// Constructor to create a recorded person
// and to open an already existing record file.
public RecordedPerson(int id)
{
super(null, -1);
m_id = id;
setRecordFile();
setBasicData();
}
// Reads the record from the record file
// and returns it as a string.
public String getRecord()
{
String data = "";
BufferedReader in = null;
try
{
in = new BufferedReader(
new FileReader(m_recordFile));
while(true)
{
String line = in.readLine();
if (line == null)
break;
data += line + "\n";
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch(IOException e)
{}
}
}
return data;
}
// Adds a new item to the record file for this person
public void addRecord(String item)
{
PrintWriter out = null;
try
{
out = new PrintWriter(
new FileWriter(
m_recordFile.getAbsolutePath(),
true));
out.println(item);
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if (out != null)
out.close();
}
}
// Creates a new record file with name and age record
// (If the record file already exists, assumes that it's valid)
private void createRecordFile()
{
setRecordFile();
if (!m_recordFile.exists())
{
// Create a new record file
PrintWriter out = null;
try
{
out = new PrintWriter(
new FileWriter(m_recordFile));
out.println(getName() + "," + getAge());
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if (out != null)
out.close();
}
}
else
{
// Assume for simplicity that the name and age
// actually correspond with the current ones.
}
}
// Sets the record File object
// If necessary, creates the subdirectory for record files.
private void setRecordFile()
{
File records = new File("records");
if (!records.exists())
records.mkdir(); // Create directory
m_recordFile = new File(records, "r" + m_id + ".rec");
}
// Reads the record file and extracts the name and age
// and sets those values for the current recorded person.
private void setBasicData()
{
// Extract the name and age from the record
String record = getRecord();
int commaIndex = record.indexOf(',');
int eolIndex = record.indexOf('\n');
String name = record.substring(0, commaIndex);
String age = record.substring(commaIndex+1, eolIndex);
// Set the name and age values
setName(name);
setAge(Integer.parseInt(age));
}
// Creates a string containing RecordedPerson information.
public String toString()
{
String s = super.toString();
s += ", ID=" + m_id + ", recordFile=" + m_recordFile;
return s;
}
private void readObject(ObjectInputStream in)
throws IOException,
ClassNotFoundException
{
in.defaultReadObject();
// Ensure that the recordFile is properly set
setRecordFile();
}
//// Data ////
private int m_id;
private transient File m_recordFile;
} |
Which produces the proper output on serialization back in:
Adding Items to the Serialized Class
If desired, you can implement your writeObject()
method in a way similar to:
private void writeObject(ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
out.writeObject(myObject); // write out additional object
}
However, if you do this, then you must also do the
equivalent when serializing back in:
private void readObject(ObjectInputStream in)
throws IOException,
ClassNotFoundException
{
in.defaultReadObject();
myObject = in.readObject(); // read in additional object
}
|