Java Tutorial/File/Object Serialization
Содержание
- 1 Class combination Serialization
- 2 Conditions for Serialization
- 3 Controlling serialization by adding your own
- 4 Deal with transient in Object Serialization
- 5 Only parent class is Serializable
- 6 Read a file of objects sequentially and displays each record
- 7 Reading an Object From a File
- 8 Saving and restoring the state of classes
- 9 Serialization Utilities
- 10 Serialization with ObjectInputStream and ObjectOutputStream
- 11 Serializing Variations on an Object
- 12 Storing Objects in a File
- 13 Writing objects sequentially to a file with class ObjectOutputStream
Class combination Serialization
<source lang="java">
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; class ID implements Serializable { } class Employee implements Serializable {
private String name; private ID myID; Employee(String nm, ID h) { name = nm; myID = h; } public String toString() { return name + "[" + super.toString() + "], " + myID + "\n"; }
} public class MainClass {
public static void main(String[] args) throws IOException, ClassNotFoundException { ID id = new ID(); List employees = new ArrayList(); employees.add(new Employee("A", id)); employees.add(new Employee("B", id)); employees.add(new Employee("C", id)); System.out.println("employees: " + employees); ByteArrayOutputStream buf1 = new ByteArrayOutputStream(); ObjectOutputStream o1 = new ObjectOutputStream(buf1); o1.writeObject(employees); o1.writeObject(employees); ByteArrayOutputStream buf2 = new ByteArrayOutputStream(); ObjectOutputStream o2 = new ObjectOutputStream(buf2); o2.writeObject(employees); ObjectInputStream in1 = new ObjectInputStream(new ByteArrayInputStream(buf1.toByteArray())); ObjectInputStream in2 = new ObjectInputStream(new ByteArrayInputStream(buf2.toByteArray())); List emp1 = (List) in1.readObject(), emp2 = (List) in1.readObject(), emp3 = (List) in2 .readObject(); System.out.println("emp1: " + emp1); System.out.println("emp2: " + emp2); System.out.println("emp3: " + emp3); }
} /*
- /</source>
employees: [A[Employee@126b249], ID@182f0db , B[Employee@192d342], ID@182f0db , C[Employee@6b97fd], ID@182f0db ] emp1: [A[Employee@750159], ID@1abab88 , B[Employee@18a7efd], ID@1abab88 , C[Employee@1971afc], ID@1abab88 ] emp2: [A[Employee@750159], ID@1abab88 , B[Employee@18a7efd], ID@1abab88 , C[Employee@1971afc], ID@1abab88 ] emp3: [A[Employee@16cd7d5], ID@cdedfd , B[Employee@1c39a2d], ID@cdedfd , C[Employee@bf2d5e], ID@cdedfd ]
Conditions for Serialization
- If a superclass of your class is not serializable, it still may be possible to make your class serializable.
- Each superclass that is not serializable must have a public default constructor - a constructor with no parameters.
- Your class must implement the Serializable interface.
- Your class must serialize and deserialize the not-serializable fields in the superclasses.
- Transient data type is not serializable.
Controlling serialization by adding your own
<source lang="java">
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MainClass {
public static void main(String[] args) throws IOException, ClassNotFoundException { MyBean sc = new MyBean("Test1", "Test2"); System.out.println("Before:\n" + sc); ByteArrayOutputStream buf = new ByteArrayOutputStream(); ObjectOutputStream o = new ObjectOutputStream(buf); o.writeObject(sc); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray())); MyBean sc2 = (MyBean) in.readObject(); System.out.println("After:\n" + sc2); }
} class MyBean implements Serializable {
private String a; private transient String b; public MyBean(String aa, String bb) { a = "Not Transient: " + aa; b = "Transient: " + bb; } public String toString() { return a + "\n" + b; } private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); stream.writeObject(b); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); b = (String) stream.readObject(); }
} /*
- /</source>
Before: Not Transient: Test1 Transient: Test2 After: Not Transient: Test1 Transient: Test2
Deal with transient in Object Serialization
<source lang="java">
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Date; public class MainClass {
public static void main(String[] args) throws Exception { User a = new User("A", "B"); System.out.println("logon a = " + a); ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("User.out")); o.writeObject(a); o.close(); Thread.sleep(1000); // Delay for 1 second ObjectInputStream in = new ObjectInputStream(new FileInputStream("User.out")); System.out.println("Recovering object at " + new Date()); a = (User) in.readObject(); System.out.println("logon a = " + a); }
} class User implements Serializable {
private Date date = new Date(); private String username; private transient String password; public User(String name, String pwd) { username = name; password = pwd; } public String toString() { String pwd = (password == null) ? "(n/a)" : password; return "logon info: \n username: " + username + "\n date: " + date + "\n password: " + pwd; }
}</source>
Only parent class is Serializable
<source lang="java">
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Random; abstract class Shape implements Serializable {
public static final int RED = 1, BLUE = 2, GREEN = 3; private int x, y, size; private static Random r = new Random(); private static int counter = 0; public abstract void setColor(int newColor); public abstract int getColor(); public Shape(int xVal, int yVal, int dim) { x = xVal; y = yVal; size = dim; } public String toString() { return getClass() + "color[" + getColor() + "] xPos[" + x + "] yPos[" + y + "] dim[" + size + "]\n"; }
} class Circle extends Shape {
private static int color = RED; public Circle(int xVal, int yVal, int dim) { super(xVal, yVal, dim); } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; }
} class Square extends Shape {
private static int color; public Square(int xVal, int yVal, int dim) { super(xVal, yVal, dim); color = RED; } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; }
} class Line extends Shape {
private static int color = RED; public static void serializeStaticState(ObjectOutputStream os) throws IOException { os.writeInt(color); } public static void deserializeStaticState(ObjectInputStream os) throws IOException { color = os.readInt(); } public Line(int xVal, int yVal, int dim) { super(xVal, yVal, dim); } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; }
} public class MainClass {
public static void main(String[] args) throws Exception { List shapeTypes, shapes; if (args.length == 0) { shapeTypes = new ArrayList(); shapes = new ArrayList(); shapeTypes.add(Circle.class); shapeTypes.add(Square.class); shapeTypes.add(Line.class); shapes.add(new Square(4, 3, 200)); shapes.add(new Circle(1, 2, 100)); shapes.add(new Line(1, 2, 100)); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("CADState.out")); out.writeObject(shapeTypes); Line.serializeStaticState(out); out.writeObject(shapes); } else { ObjectInputStream in = new ObjectInputStream(new FileInputStream(args[0])); shapeTypes = (List) in.readObject(); Line.deserializeStaticState(in); shapes = (List) in.readObject(); } System.out.println(shapes); }
} /*
- /</source>
[class Squarecolor[1] xPos[4] yPos[3] dim[200] , class Circlecolor[1] xPos[1] yPos[2] dim[100] , class Linecolor[1] xPos[1] yPos[2] dim[100] ]
Read a file of objects sequentially and displays each record
<source lang="java">
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MainClass {
public static void main(String[] args) throws Exception { ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("clients.ser")); AccountRecordSerializable record; record = new AccountRecordSerializable(1, "firstName", "lastName", 0.1); output.writeObject(record); ObjectInputStream input = new ObjectInputStream(new FileInputStream("clients.ser")); record = (AccountRecordSerializable) input.readObject(); System.out.printf("%-10d%-12s%-12s%10.2f\n", record.getAccount(), record.getFirstName(), record .getLastName(), record.getBalance()); output.close(); }
} class AccountRecordSerializable implements Serializable {
private int account; private String firstName; private String lastName; private double balance; public AccountRecordSerializable() { this(0, "", "", 0.0); } public AccountRecordSerializable(int acct, String first, String last, double bal) { setAccount(acct); setFirstName(first); setLastName(last); setBalance(bal); } public void setAccount(int acct) { account = acct; } public int getAccount() { return account; } public void setFirstName(String first) { firstName = first; } public String getFirstName() { return firstName; } public void setLastName(String last) { lastName = last; } public String getLastName() { return lastName; } public void setBalance(double bal) { balance = bal; } public double getBalance() { return balance; }
}</source>
Reading an Object From a File
<source lang="java">
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MainClass {
public static void main(String[] args) throws Exception { Junk obj1 = new Junk("A"); Junk obj2 = new Junk("B"); Junk obj3 = new Junk("V"); ObjectOutputStream objectOut = new ObjectOutputStream(new BufferedOutputStream( new FileOutputStream("C:/JunkObjects.bin"))); objectOut.writeObject(obj1); // Write object objectOut.writeObject(obj2); // Write object objectOut.writeObject(obj3); // Write object objectOut.close(); // Close the output stream ObjectInputStream objectIn = null; int objectCount = 0; Junk object = null; objectIn = new ObjectInputStream(new BufferedInputStream(new FileInputStream( "C:/JunkObjects.bin"))); // Read from the stream until we hit the end while (objectCount < 3) { object = (Junk) objectIn.readObject(); objectCount++; System.out.println(object); } objectIn.close(); }
} class Junk implements Serializable {
String str; public Junk(String s) { str = s; }
}</source>
Saving and restoring the state of classes
<source lang="java">
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Random; abstract class Shape implements Serializable {
public static final int RED = 1, BLUE = 2, GREEN = 3; private int x, y, size; private static Random r = new Random(); private static int counter = 0; public abstract void setColor(int newColor); public abstract int getColor(); public Shape(int xVal, int yVal, int dim) { x = xVal; y = yVal; size = dim; } public String toString() { return getClass() + "color[" + getColor() + "] xPos[" + x + "] yPos[" + y + "] dim[" + size + "]\n"; }
} class Circle extends Shape {
private static int color = RED; public Circle(int xVal, int yVal, int dim) { super(xVal, yVal, dim); } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; }
} class Square extends Shape {
private static int color; public Square(int xVal, int yVal, int dim) { super(xVal, yVal, dim); color = RED; } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; }
} class Line extends Shape {
private static int color = RED; public static void serializeStaticState(ObjectOutputStream os) throws IOException { os.writeInt(color); } public static void deserializeStaticState(ObjectInputStream os) throws IOException { color = os.readInt(); } public Line(int xVal, int yVal, int dim) { super(xVal, yVal, dim); } public void setColor(int newColor) { color = newColor; } public int getColor() { return color; }
} public class MainClass {
public static void main(String[] args) throws Exception { List shapeTypes, shapes; if (args.length == 0) { shapeTypes = new ArrayList(); shapes = new ArrayList(); shapeTypes.add(Circle.class); shapeTypes.add(Square.class); shapeTypes.add(Line.class); shapes.add(new Square(4, 3, 200)); shapes.add(new Circle(1, 2, 100)); shapes.add(new Line(1, 2, 100)); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("CADState.out")); out.writeObject(shapeTypes); Line.serializeStaticState(out); out.writeObject(shapes); } else { ObjectInputStream in = new ObjectInputStream(new FileInputStream(args[0])); shapeTypes = (List) in.readObject(); Line.deserializeStaticState(in); shapes = (List) in.readObject(); } System.out.println(shapes); }
} /*
- /</source>
[class Squarecolor[1] xPos[4] yPos[3] dim[200] , class Circlecolor[1] xPos[1] yPos[2] dim[100] , class Linecolor[1] xPos[1] yPos[2] dim[100] ]
Serialization Utilities
<source lang="java">
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"); } }
}</source>
Serialization with ObjectInputStream and ObjectOutputStream
<source lang="java">
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); }
}</source>
Serializing Variations on an Object
<source lang="java">
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class Data implements Serializable {
private int value; public Data(int init) { value = init; } public boolean equals(Object obj) { if (obj instanceof Data && ((Data) obj).value == value) { return true; } return false; } public void setValue(int val) { value = val; } public int getValue() { return value; }
} public class MainClass {
public static void main(String[] args) { Data data = new Data(1); try { ObjectOutputStream objectOut = new ObjectOutputStream(new BufferedOutputStream( new FileOutputStream("C:/test.bin"))); objectOut.writeObject(data); System.out.println("1st Object written has value: " + data.getValue()); data.setValue(2); objectOut.writeObject(data); System.out.println("2nd Object written has value: " + data.getValue()); data.setValue(3); objectOut.writeObject(data); System.out.println("3rd Object written has value: " + data.getValue()); objectOut.close(); } catch (IOException e) { e.printStackTrace(System.err); } try { ObjectInputStream objectIn = new ObjectInputStream(new BufferedInputStream( new FileInputStream("C:/test.bin"))); Data data1 = (Data) objectIn.readObject(); Data data2 = (Data) objectIn.readObject(); Data data3 = (Data) objectIn.readObject(); System.out.println(data1.equals(data2)); System.out.println(data2.equals(data3)); System.out.println(data1.getValue()); System.out.println(data2.getValue()); System.out.println(data3.getValue()); objectIn.close(); } catch (Exception e) { e.printStackTrace(System.err); } }
}</source>
1st Object written has value: 1 2nd Object written has value: 2 3rd Object written has value: 3 true true 1 1 1
Storing Objects in a File
<source lang="java">
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MainClass {
public static void main(String[] args) throws Exception { Junk obj1 = new Junk("A"); Junk obj2 = new Junk("B"); Junk obj3 = new Junk("V"); ObjectOutputStream objectOut = new ObjectOutputStream(new BufferedOutputStream( new FileOutputStream("C:/JunkObjects.bin"))); objectOut.writeObject(obj1); // Write object objectOut.writeObject(obj2); // Write object objectOut.writeObject(obj3); // Write object System.out.println("\n\nobj1:\n" + obj1 + "\n\nobj2:\n" + obj2 + "\n\nobj3:\n" + obj3); objectOut.close(); // Close the output stream }
} class Junk implements Serializable{
String str; public Junk(String s) { str = s; }
}</source>
obj1: Junk@c2a132 obj2: Junk@337d0f obj3: Junk@1e4cbc4
Writing objects sequentially to a file with class ObjectOutputStream
<source lang="java">
import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MainClass {
public static void main(String[] args) throws Exception { ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("clients.ser")); AccountRecordSerializable record; record = new AccountRecordSerializable(1, "firstName", "lastName", 0.1); output.writeObject(record); output.close(); }
} class AccountRecordSerializable implements Serializable {
private int account; private String firstName; private String lastName; private double balance; public AccountRecordSerializable() { this(0, "", "", 0.0); } public AccountRecordSerializable(int acct, String first, String last, double bal) { setAccount(acct); setFirstName(first); setLastName(last); setBalance(bal); } public void setAccount(int acct) { account = acct; } public int getAccount() { return account; } public void setFirstName(String first) { firstName = first; } public String getFirstName() { return firstName; } public void setLastName(String last) { lastName = last; } public String getLastName() { return lastName; } public void setBalance(double bal) { balance = bal; } public double getBalance() { return balance; }
}</source>