1. 객체의 직렬화와 역직렬화


1) 객체의 직렬화(serialization) : 객체를 스트림으로 만드는 작업

2) 객체의 역직렬화(deserialization) : 스트림으로부터 다시 객체를 만드는 작업


자바에서는 모든 입출력 데이터를 스트림 형태로 주고받는다. 그렇기 때문에 객체를 파일에 저장하거나 네트워크로 전송하기 위해서는 객체를 스트림으로 만드는 작업이 필요하다. 이렇게 객체를 스트림으로 만드는 것을 직렬화, 스트림에서 객체를 만드는 것을 역직렬화라고 한다.



3) 객체의 직렬화와 역직렬화 기능을 제공하는 클래스

1) java.io.ObjectOutputStream

2) java.io.ObjectInputStream

※ java.io.Serializable 인터페이스를 구현하는 클래스는 모두 직렬화 가능 클래스. 그 외의 클래스는 모두 직렬화 가능 클래스가 아니다.



예제) 객체의 직렬화와 역직렬화 (writeObject, readObject)


1) 객체를 직렬화하는 프로그램


import java.io.*;

import java.util.GregorianCalendar;

class ObjectOutputExample1 {

    public static void main(String args[]) {

        ObjectOutputStream out = null;

        try {

            out = new ObjectOutputStream(new FileOutputStream("output.dat"));

            out.writeObject(new GregorianCalendar(2006, 0, 14));

            out.writeObject(new GregorianCalendar(2006, 0, 15));

            out.writeObject(new GregorianCalendar(2006, 0, 16));

        }

        catch (IOException ioe) {

            System.out.println("파일로 출력할 수 없습니다.");

        }

        finally {

            try {

                out.close();

            }          

            catch (Exception e) {

            }

        }

    }

}

writeObject 메소드 : 파라미터로 넘겨준 객체를 스트림으로 만들어서 출력하는 메소드



1) 객체를 역직렬화하는 프로그램


import java.util.GregorianCalendar;

import java.util.Calendar;

class ObjectInputExample1 {

    public static void main(String args[]) {

        ObjectInputStream in = null;

        try {

            in = new ObjectInputStream(

                  new FileInputStream("output.dat"));

            while (true) {

                GregorianCalendar calendar = (GregorianCalendar) in.readObject();

                int year = calendar.get(Calendar.YEAR);

                int month = calendar.get(Calendar.MONTH) + 1;

                int date = calendar.get(Calendar.DATE);

                System.out.println(year + "/" + month + "/" + date);

            }

        }

        catch (FileNotFoundException fnfe) {

            System.out.println("파일이 존재하지 않습니다.");

        }

        catch (EOFException eofe) {

            System.out.println("끝");

        }

        catch (IOException ioe) {

            System.out.println("파일을 읽을 수 없습니다.");

        }

        catch (ClassNotFoundException cnfe) {

            System.out.println("해당 클래스가 존재하지 않습니다.");

        }

        finally {

            try {

                in.close();

            }          

            catch (Exception e) {

            }

        }

    }

}

readObject 메소드 : 입력된 스트림으로부터 객체를 만들어서 리턴하는 메소드




2. 직렬화 가능 클래스의 선언 방법


- java.io.Serializable 인터페이스를 구현하는 클래스는 모두 직렬화 가능 클래스

- 직접 클래스를 선언할 때 java.io.Serializable 인터페이스를 구현하면 직렬화 가능 클래스가 될 것인가? (X)


예제) 


1) 재고 정보 클래스 (직렬화 불가능)

class GoodsStock {  

    String code;       

    int num;           

    GoodsStock(String code, int num) {   

        this.code = code;

        this.num = num;

    }

    void addStock(int num) {  

        this.num += num;              

    }

    int subtractStock(int num) throws Exception {  

        if (this.num < num)

            throw new Exception("재고가 부족합니다.");

        this.num -= num;            

        return num;

    }

}


2) 재고 정보 클래스 (직렬화 가능)

class GoodsStock implements java.io.Serializable {  

    String code;       

    int num;           

    GoodsStock(String code, int num) {   

        this.code = code;

        this.num = num;

    }

    void addStock(int num) {  

        this.num += num;              

    }

    int subtractStock(int num) throws Exception {  

        if (this.num < num)

            throw new Exception("재고가 부족합니다.");

        this.num -= num;            

        return num;

    }

}

※ 위의 예제의 경우 implements java.io.Serializable를 붙인 것만으로 직렬화가 가능해진다.



3) GoodsStock 객체를 직렬화하는 프로그램


import java.io.*;

class ObjectOutputExample2 {

    public static void main(String args[]) {

        ObjectOutputStream out = null;

        try {

            out = new ObjectOutputStream(

                   new FileOutputStream("output2.dat"));

            out.writeObject(new GoodsStock("70101", 100));

            out.writeObject(new GoodsStock("70102", 50));

            out.writeObject(new GoodsStock("70103", 200));

        }

        catch (IOException ioe) {

            System.out.println("파일로 출력할 수 없습니다.");

        }

        finally {

            try {

                out.close();

            }          

            catch (Exception e) {

            }

        }

    }

}



4) GoodsStock 객체를 역직렬화하는 프로그램

import java.io.*;

class ObjectInputExample2 {

    public static void main(String args[]) {

        ObjectInputStream in = null;

        try {

            in = new ObjectInputStream(

                   new FileInputStream("output2.dat"));

            while (true) {

                GoodsStock obj = (GoodsStock) in.readObject();

                System.out.println("상품코드:" + obj.code + "\t상품수량:" + obj.num);

            }

        }

        catch (FileNotFoundException fnfe) {

            System.out.println("파일이 존재하지 않습니다.");

        }

        catch (EOFException eofe) {

            System.out.println("끝");

        }

        catch (IOException ioe) {

            System.out.println("파일을 읽을 수 없습니다.");

        }

        catch (ClassNotFoundException cnfe) {

            System.out.println("해당 클래스가 존재하지 않습니다.");

        }

        finally {

            try {

                in.close();

            }          

            catch (Exception e) {

            }

        }

    }

}


결과) java.io.Serializable 인터페이스를 구현했을 때 writeObject 메소드와 readObject 메소드를 이용해서 파일에 읽고 쓸 수 있다.
상품코드:70101 상품수량:100
상품코드:70102 상품수량:50
상품코드:70103 상품수량:200

















Posted by netyhobby
,