Java的IO操作(三) – 對象的序列化、ObjectInputStream和ObjectOutputStream類

來源:互聯網
上載者:User

由於Java是一種完全物件導向的進階語言,所以在編寫程式的時候資料大都存放在對象當中。我們有時會需要將記憶體中的整個對象都寫入到檔案中去,然後在適當的時候再從檔案中將對象還原至記憶體。我們可以使用java.io.ObjectInputStream和java.io.ObjectOutputStream類來完成這個任務。

1、對象的序列化(Serialize)

序列化是指將對象的狀態資訊轉換為可以儲存或傳輸的形式的過程。在序列化期間,對象將其目前狀態寫入到臨時或持久性儲存區。以後,可以通過從儲存區中讀取或還原序列化對象的狀態,重新建立該對象。

2、ObjectInputStream類 和ObjectOutputStream類

如果我們想要序列化一個對象,如我們自訂的User類的對象,那麼這個對象必須實現Serializable介面Serializable介面沒有任何的抽象方法,實現這個介面僅僅是為了通知編譯器這個對象將要被序列化而已。類似的用法還有Cloneable介面,實現這個介面也只是起到通知編譯器的作用。

為了示範如何進行對象的序列化,我們先設計一個User類:

package cls;import java.io.*;public class User implements Serializable // 實現Serializable介面,僅僅直到標識這個類可被序列化的作用{    // 可序列化對象的版本    private static final long serialVersionUID = 1L;        private String name;    private int num;        public User(String name,int num)    {        this.name = name;        this.num = num;    }    public String getName()    {        return name;    }    public int getNum()    {        return num;    }}

注意,seriaVersionUID是指可序列化對象的版本。如果我們沒有指定這個版本,那麼編譯器為自動為實現Serializable介面的類產生一個seriaVersionUID。如果是自動產生的,那麼一次如果更改了User類,則自動產生的seriaVersionUID就會不同。在從檔案中讀回對象時,如果兩個對象的seriaVersionUID不同,就會拋出java.io.InvalidClassException。因此如果我們今後不需要改動User類的話,最好自己指定seriaVersionUID,以防止發生該異常。

下面我們使用ObjectInputStream類 和ObjectOutputStream類 向檔案中寫入3個User對象,追加1個User對象,最後再從檔案中讀回對象。

package cls;import java.io.*;import java.util.*;import cls.User;public class ObjectStreamDemo{    public static void main(String[] args)    {        User[] user = new User[]{new User("dogg",1),new User("catt",2),new User("pigg",3)};                // 向檔案中寫入對象        try        {            ObjectStreamDemo.writeObj(user,args[0]);        }        catch(Exception e)        {            System.out.println(e.toString());        }                // 向檔案中追加對象        try        {            // 要追加的對象            User[] u = new User[]{new User("append1",4),new User("append2",5)};                        ObjectStreamDemo.appendObj(u,args[0]);        }        catch(Exception e)        {            System.out.println(e.toString());        }        // 讀取對象        try        {            List<User> list = ObjectStreamDemo.readObj(args[0]);                        // 輸出對象資訊            Iterator<User> it = list.iterator();            while(it.hasNext())            {                User temp = it.next();                System.out.println(temp.getName() + "," + temp.getNum());            }        }        catch(Exception e)        {            System.out.println(e.toString());        }    }        static private void appendObj(Object[] objs,String fileName) throws Exception    {        File file = new File(fileName);                // 以追加模式建立檔案流對象        FileOutputStream fis = new FileOutputStream(file,true);        ObjectOutputStream oos = new ObjectOutputStream(fis)        {            // 重寫 writeStreamHeader()方法,空實現            protected void writeStreamHeader(){};        };                // 寫入資料        for(Object o : objs)        {            oos.writeObject(o);        }                // 關閉流        oos.close();    }    static private List<User> readObj(String fileName) throws Exception    {        File file = new File(fileName);                // 使用List儲存讀取出來的對象        ArrayList<User> list = new ArrayList<User>();                // 建立流對象        FileInputStream fis = new FileInputStream(file);        ObjectInputStream ois = new ObjectInputStream(fis);                // 讀取對象並放入List容器中        while(fis.available() > 0)        {            list.add((User)ois.readObject());        }                ois.close();        return list; // 返回List    }        static private void writeObj(Object[] objs,String fileName) throws Exception    {        // 使用命令列參數中指定的檔案名稱        File file = new File(fileName);                // 建立流對象        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));                // 寫入對象        for(Object o : objs)        {            oos.writeObject(o);        }                // 關閉流        oos.close();    }}

注意,當我們想要向一個已經存在的檔案中追加對象時,應該重寫ObjectOutputStream的writeStreamHeader()方法,並空實現。因為,ObjectOutputStream在寫入資料的時候會加上一個特別的流頭(Stream Header),在讀取資料的時候會先檢查這個流頭。所以我們在向檔案中追加對象的時候ObjectOutputStream就會再次向檔案中寫入流頭,這樣在讀取對象的時候會發生StreamCorrupedException異常。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.