자바 객체 직렬화 방법 ObjectInputStream, ObjectOutputStream

자바(JAVA)

자바 객체 직렬화 방법 ObjectInputStream, ObjectOutputStream

 

환경 :  Eclipse Mars, Android 4.2.2

 

객체의 직렬화는 전송할 데이터를 바이트 단위로 변환하는 과정을 말합니다. 그대로 바이트로 변환한 뒤 일렬로 나열하는 것이죠. 그러니까 네트워트를 통해서 보내거나 파일로 저장하기 위해서 직렬화를 하는 것입니다. 자바에서 객체 직렬화는 아무리 복잡한 내용이라도 손쉽게 바이트 변환을 할수 있도록 만들어 놓았습니다. 보내는 쪽에서 직렬화를 했다면 내용을 받거나 다시 읽어들이기 위해서 복원을 해야 겠죠. 이런 과정을 자바 I/O 클래스가 자동으로 해 줍니다.

 

직렬화에 필요한 클래스

 

▼ 직렬화를 해야할 객체가 있다면 java.io.Serializable 인터페이스를 상속받아야 합니다.

Serializable 인터페이스는 내부에 구현해야할 함수가 없습니다. 단순히 JVM 가상머신에직렬화 대상이라고 알리는 역할만 합니다. 다음은 객체를 직렬화할 때 쓰이는 클래스들입니다.

 

ObjectInputStream : 파일이나 네트워크를 통해 전달 받은 직열화된 데이터를 다시

원래대로 돌리는 역할을 합니다. 직렬화 하기전 객체로 다시 만드는 것이죠. 이때 쓰이는 함수가 readObject() 이며 직렬화 하기전 객체로 캐스팅을 해야 겠죠

 

ObjectOutputStream : 파일이나 네트워크로 데이터를 전달하기 위해 직렬화를 수행합니다. writeObject() 함수를 이용해서 변환합니다.

 

serialVersionUID 버전이 필요한 이유?

 

Serializable 이 포함된 직렬화 객체에 serialVersionUID 값을 포함시키는 이유는 다시 역직렬화를 해서 읽어 들일 때 현재 캐스팅한 클래스에 포함되어 있는 serialVersionUID 번호와 역직렬화한 객체의 serialVersionUID 번호가 맞는지 확인하기 위해서 입니다. 이것이 맞지 않는다면 상태가 변경되었다고 판단하고 예외를 발생 시킵니다.

 

java.io.InvalidClassException: User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

 

 

직렬화 수행을 위한 파일 저장과 읽기

 

▼ 우선 파일저장을 위해서는 FileOutputStream 클래스가 필요합니다. 파일이 저장될 위치를 인수로 받아서 객체를 생성한뒤 직렬화를 위해 ObjectOutputStream 클래스를

사용하였습니다. 직렬화를 만드는 함수는 writeObject() 입니다. Serializable 인터페이스를 상속받은 User 객체를 인수로 넘깁니다.  

 

// 마샬링(marshalling) 수행, 직렬화 
public void doSerializable() throws IOException {

	FileOutputStream fos = new FileOutputStream(filePath);
	ObjectOutputStream oos = new ObjectOutputStream(fos);
	oos.writeObject(user);
	oos.close();
}

 

직렬화한 파일을 다시 읽어 들이기 위해 FileInputStream ObjectInputStream 클래스를 사용하였습니다. 읽어들이는 함수는 readObject() 이며 해당 객체로 채스팅을 해 줘야 겠죠. 

 

// 언마샬링(unmarshalling) 수행, 역직렬화
public Object undoSerializable() throws IOException, ClassNotFoundException {

	FileInputStream fis = new FileInputStream(filePath);
	ObjectInputStream ois = new ObjectInputStream(fis);
	Object user = ois.readObject();
	ois.close();
	
	return user;
}

 

직렬화 전체 소스

 

init() 함수에서 직렬화 객체에 데이터를 셋팅한후 doSerializable() 함수를 이용해서 직렬화하고 파일로 저장합니다. 그리고 다시 undoSerializable() 함수를 이용해서 직렬화를 해제한뒤 콘솔에 그 값을 찍는 내용입니다. 

 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Main {

	private String filePath;
	private User user;
	public static void main(String[] args){
		
		Main main = new Main();
		try {
			main.init();
			main.doSerializable();
			User user = (User) main.undoSerializable();
			
			System.out.println(user.getName());
			System.out.println(user.getAge());
			System.out.println(user.getPhoneNumber());
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void init() {

		filePath = "C:\\user.ser";
		
		user = new User();
		user.setName("kim dong");
		user.setAge(50);
		user.setPhoneNumber("010-9858-9985");
	}
	
	// 마샬링(marshalling) 수행, 직렬화 
	public void doSerializable() throws IOException {

		FileOutputStream fos = new FileOutputStream(filePath);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(user);
		oos.close();
	}
    
	// 언마샬링(unmarshalling) 수행, 역직렬화
	public Object undoSerializable() throws IOException, ClassNotFoundException {

		FileInputStream fis = new FileInputStream(filePath);
		ObjectInputStream ois = new ObjectInputStream(fis);
		Object user = (User) ois.readObject();
		ois.close();
		
		return user;
	}
}

// 직렬화 객체 
class User implements Serializable {
	private static final long serialVersionUID = 2L;
	private String name;
	private int age;
	private String phoneNumber;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPhoneNumber() {
		return phoneNumber;
	}
	public void setPhoneNumber(String socialNumber) {
		this.phoneNumber = socialNumber;
	}
}
// 결과
kim dong
50
010-9858-9985
Posted by 녹두장군

댓글을 달아 주세요