Java序列化與反序列化(實踐)

 

基本概念:
序列化是將對象狀態轉換爲可保持或傳輸的格式的過程。與序列化相對的是反序列化,它將流轉換爲對象。這兩個過程結合起來,可以輕鬆地存儲和傳輸數據。

昨天在一本書上看到了,好好實踐了一下,序列化爲一般文件,也序列化爲XML文件(使用XStream)。

用於序列化的實體類Person.java    代碼如下(記得需要實現Serializable接口):
import java.io.Serializable;

@SuppressWarnings("serial")
public class Person implements Serializable{
    private String name;
    private int age;
    public Person(){
       
    }
    public Person(String str, int n){
        System.out.println("Inside Person's Constructor");
        name = str;
        age = n;
    }
    String getName(){
        return name;
    }
    int getAge(){
        return age;
    }
}



序列化、反序列化爲一般的文件,SerializeToFlatFile.java類的代碼如下:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;


public class SerializeToFlatFile {
    public static void main(String[] args) {
        SerializeToFlatFile ser = new SerializeToFlatFile();
        ser.savePerson();
        ser.restorePerson();       
    }
   
    public void savePerson(){
        Person myPerson = new Person("Jay",24);
        try {
            FileOutputStream fos = new FileOutputStream("E:\\workspace\\2010_03\\src\\myPerson.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            System.out.println("Person--Jay,24---Written");
            System.out.println("Name is: "+myPerson.getName());
            System.out.println("Age is: "+myPerson.getAge());
           
            oos.writeObject(myPerson);
            oos.flush();
            oos.close();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
   
    public void restorePerson() {
        try {
            FileInputStream fis = new FileInputStream("E:\\workspace\\2010_03\\src\\myPerson.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
           
            Person myPerson = (Person)ois.readObject();
            System.out.println("\n--------------------\n");
            System.out.println("Person--Jay,24---Restored");
            System.out.println("Name is: "+myPerson.getName());
            System.out.println("Age is: "+myPerson.getAge());
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}
運行結果爲(console輸出),當然可以查看到myPerson.txt文件已經生成:
Inside Person's Constructor
Person--Jay,24---Written
Name is: Jay
Age is: 24

--------------------

Person--Jay,24---Restored
Name is: Jay
Age is: 24


序列化、反序列化爲XML文件,我使用了XStream來序列化,需要引入xstream-1.3.1.jar包的支持,
http://xstream.codehaus.org/download.html  處可以下載jar,然後引入到Eclipse中的build path中。
Serialize.java的代碼如下:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import com.thoughtworks.xstream.*;

public class Serialize {
    public static void main(String[] args) {
        Serialize ser = new Serialize();
        ser.serializeToXml();
        ser.deSerializeFromXml();
    }
   
public void serializeToXml(){
        Person[] myPerson = new Person[2];
        myPerson[0] = new Person("Jay",24);
        myPerson[1] = new Person("Tom",23);
       
        XStream xstream = new XStream(); 
        try {
            FileOutputStream fos = new FileOutputStream("E:\\workspace\\2010_03\\src\\myPerson.xml");
             xstream.toXML(myPerson,fos);
             } catch (FileNotFoundException ex) {
             ex.printStackTrace();
             }      
        System.out.println(xstream.toXML(myPerson));
    }
    public void deSerializeFromXml(){
         XStream xs = new XStream();
         Person[] myPerson = null;

         try {
         FileInputStream fis = new FileInputStream("E:\\workspace\\2010_03\\src\\myPerson.xml");
         myPerson=(Person[])xs.fromXML(fis);
         if (myPerson != null)
         {
             int len = myPerson.length;
             for (int i=0;i<len;i++)
             {
                 System.out.println(myPerson[i].getName());
                 System.out.println(myPerson[i].getAge());
             }

         }
         } catch (FileNotFoundException ex) {
         ex.printStackTrace();
         }
    }
}
運行結果爲(console輸出),當然可以查看到myPerson.xml文件已經生成:
Inside Person's Constructor
Inside Person's Constructor
<Person-array>
  <Person>
    <name>Jay</name>
    <age>24</age>
  </Person>
  <Person>
    <name>Tom</name>
    <age>23</age>
  </Person>
</Person-array>
Jay
24
Tom
23


參考資料:
http://developer.51cto.com/art/200908/147650.htm
http://www.ibm.com/developerworks/cn/xml/x-xstream/#resources
http://www.cnblogs.com/stephencat/archive/2007/06/05/772520.html

 

轉載:http://renyongjie668.blog.163.com/blog/static/1600531201022105142865/

 

 

 

 

這次我們講的是控制對象的序列化和反序列化

 

控制序列化就是有選擇的序列化對象,而不是把對象的所以內容都序列化,前篇我們的例子中介紹了transit變量和類變量(static)不被序列化,現在我們還有一種更爲靈活的控制對象序列化和反序列方法,可以在序列化過程中儲存其他非this對象包含的數據

 

我們現在再來介紹一個接口 java.io.Externalizable 。當對象實現了這個接口時,就可以靈活的控制它的序列化和反序列過程,這個接口繼承了java.io.Serializable

 

Externalizable 接口定義了兩個方法,writerExternal方法在序列化時被調用,可以再該方法中控制序列化內容,readExternal方法在反序列時被調用,可以在該方法中控制反序列的內容

 

好了,現在我們改寫上例的UserInfo

 

Java代碼 複製代碼
  1. import java.io.*;   
  2. import java.util.*;   
  3.   
  4. //本程序通過實現Externalizable接口控制對象序列化和反序列   
  5. public class UserInfo implements Externalizable {   
  6.     public String userName;   
  7.     public String userPass;   
  8.     public int userAge;   
  9.   
  10.     public UserInfo(){   
  11.     }   
  12.   
  13.     public UserInfo(String username,String userpass,int userage){   
  14.         this.userName=username;   
  15.         this.userPass=userpass;   
  16.         this.userAge=userage;   
  17.     }   
  18.        
  19.     //當序列化對象時,該方法自動調用   
  20.     public void writeExternal(ObjectOutput out) throws IOException{   
  21.         System.out.println("現在執行序列化方法");   
  22.         //可以在序列化時寫非自身的變量   
  23.         Date d=new Date();   
  24.         out.writeObject(d);   
  25.         //只序列化userName,userPass變量   
  26.         out.writeObject(userName);   
  27.         out.writeObject(userPass);   
  28.     }   
  29.   
  30.     //當反序列化對象時,該方法自動調用   
  31.     public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{   
  32.         System.out.println("現在執行反序列化方法");   
  33.         Date d=(Date)in.readObject();   
  34.         System.out.println(d);   
  35.         this.userName=(String)in.readObject();   
  36.         this.userPass=(String)in.readObject();   
  37.     }   
  38.   
  39.     public String toString(){   
  40.         return "用戶名: "+this.userName+";密碼:"+this.userPass+   
  41.             ";年齡:"+this.userAge;   
  42.     }   
  43. }  

 

import java.io.*;
import java.util.*;

//本程序通過實現Externalizable接口控制對象序列化和反序列
public class UserInfo implements Externalizable {
	public String userName;
	public String userPass;
	public int userAge;

	public UserInfo(){
	}

	public UserInfo(String username,String userpass,int userage){
		this.userName=username;
		this.userPass=userpass;
		this.userAge=userage;
	}
	
	//當序列化對象時,該方法自動調用
	public void writeExternal(ObjectOutput out) throws IOException{
		System.out.println("現在執行序列化方法");
		//可以在序列化時寫非自身的變量
		Date d=new Date();
		out.writeObject(d);
		//只序列化userName,userPass變量
		out.writeObject(userName);
		out.writeObject(userPass);
	}

	//當反序列化對象時,該方法自動調用
	public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException{
		System.out.println("現在執行反序列化方法");
		Date d=(Date)in.readObject();
		System.out.println(d);
		this.userName=(String)in.readObject();
		this.userPass=(String)in.readObject();
	}

	public String toString(){
		return "用戶名: "+this.userName+";密碼:"+this.userPass+
			";年齡:"+this.userAge;
	}
}

 

改寫測試類

 

Java代碼 複製代碼
  1. import java.io.ObjectOutputStream;   
  2. import java.io.ObjectInputStream;   
  3. import java.io.FileInputStream;   
  4. import java.io.FileOutputStream;   
  5. import java.util.Date;   
  6. import java.lang.management.*;   
  7. public class Test {   
  8.   
  9.   
  10.   
  11.     //序列化對象到文件   
  12.     public static void serialize(String fileName){   
  13.         try  
  14.         {   
  15.             //創建一個對象輸出流,講對象輸出到文件   
  16.             ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));   
  17.   
  18.             UserInfo user=new UserInfo("renyanwei","888888",20);   
  19.             out.writeObject(user);  //序列化一個會員對象   
  20.   
  21.             out.close();   
  22.         }   
  23.         catch (Exception x)   
  24.         {   
  25.             System.out.println(x.toString());   
  26.         }   
  27.            
  28.     }   
  29.     //從文件反序列化到對象   
  30.     public static void deserialize(String fileName){   
  31.         try  
  32.         {   
  33.             //創建一個對象輸入流,從文件讀取對象   
  34.             ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));   
  35.   
  36.             //讀取UserInfo對象並調用它的toString()方法   
  37.             UserInfo user=(UserInfo)(in.readObject());             
  38.             System.out.println(user.toString());   
  39.   
  40.             in.close();   
  41.         }   
  42.         catch (Exception x)   
  43.         {   
  44.             System.out.println(x.toString());   
  45.         }   
  46.            
  47.     }   
  48.   
  49.     public static void main(String[] args) {       
  50.   
  51.         serialize("D:\\test.txt");   
  52.         System.out.println("序列化完畢");   
  53.            
  54.         deserialize("D:\\test.txt");   
  55.         System.out.println("反序列化完畢");   
  56.     }   
  57.   
  58. }  

 

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.lang.management.*;
public class Test {



	//序列化對象到文件
	public static void serialize(String fileName){
		try
		{
			//創建一個對象輸出流,講對象輸出到文件
			ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(fileName));

			UserInfo user=new UserInfo("renyanwei","888888",20);
			out.writeObject(user);	//序列化一個會員對象

			out.close();
		}
		catch (Exception x)
		{
			System.out.println(x.toString());
		}
		
	}
	//從文件反序列化到對象
	public static void deserialize(String fileName){
		try
		{
			//創建一個對象輸入流,從文件讀取對象
			ObjectInputStream in=new ObjectInputStream(new FileInputStream(fileName));

			//讀取UserInfo對象並調用它的toString()方法
			UserInfo user=(UserInfo)(in.readObject());			
			System.out.println(user.toString());

			in.close();
		}
		catch (Exception x)
		{
			System.out.println(x.toString());
		}
		
	}

	public static void main(String[] args) {	

		serialize("D:\\test.txt");
		System.out.println("序列化完畢");
		
		deserialize("D:\\test.txt");
		System.out.println("反序列化完畢");
	}

}

  執行結果

現在執行序列化方法
序列化完畢
現在執行反序列化方法
Thu Oct 23 22:18:12 CST 2008
用戶名: renyanwei;密碼:888888;年齡:0
反序列化完畢

 

通過一張圖來看程序流程

首先,我們在序列化UserInfo對象的時候,由於這個類實現了Externalizable 接口,在writeExternal()方法裏定義了哪些屬性可以序列化,哪些不可以序列化,所以,對象在經過這裏就把規定能被序列化的序列化保存文件,不能序列化的不處理,然後在反序列的時候自動調用readExternal()方法,根據序列順序挨個讀取進行反序列,並自動封裝成對象返回,然後在測試類接收,就完成了反序列

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章