[JavaStudy] 6. 직렬화 ? 역직렬화 ?

진주·2022년 3월 17일
0

JavaStudy

목록 보기
6/9

직렬화(Serialization) ?

우리는 파일에 텍스트를 기록하고, 이진 데이터를 기록하는 방법은 많이 알고있다.

그런데 만약, 이런 종류의 데이터들이 아니라 객체를 파일로 저장하거나 읽어오려면 직렬화를 배워야한다.

Account라는 클래스는 email, 이름, 주소, 전화번호, 등록일자를 멤버로 갖는 클래스이다.

이것을 객체화하여 파일이나 네트워크로 write할 때는 직렬화를 거쳐 전달된다.

반대로 읽어올 경우에는, 역직렬화(Deserialization)을 거쳐서 가져오게 된다.

  • Java 직렬화는
    자바 시스템 내부에서 사용되는 객체 또는 데이터들을 외부의 자바 시스템에서도 사용할 수 있도록
    바이트(byte) 형태로 데이터 변환하는 기술
    바이트로 변환된 데이터를 다시 객체로 변환하는 역직렬화를 포함합니다.
  • 시스템적으로 JVM의 Runtim Data Area(Heap 또는 스택영역)에 상주하고 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 말하기도 합니다.

1) 직렬화가 가능한 클래스 구현하기

Account.java 파일 생성

import java.util.Date;
import java.io.Serializable;

class Account implements Serializable{

  private String email;
  private String name;
  private String address;
  private String phone;
  private Date reg_date;

  public Account(String email, String name, String address, String phone, Date reg_date) {
    this.email = email;
    this.name = name;
    this.address = address;
    this.phone = phone;
    this.reg_date = reg_date;
  }
  
   public Account(String email, String name, String address, String phone) {
    this.email = email;
    this.name = name;
    this.address = address;
    this.phone = phone;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getPhone() {
    return phone;
  }

  public void setPhone(String phone) {
    this.phone = phone;
  }

  public Date getReg_date() {
    return reg_date;
  }

  public void setReg_date(Date reg_date) {
    this.reg_date = reg_date;
  }

  @Override
  public String toString() {
    return "Account [address=" + address + ", email=" + email + ", name=" + name + ", phone=" + phone + ", reg_date="
        + reg_date + "]";
  }
}

email, name, address, phone, reg_date를 변수로 선언한 뒤,

Getter,Setter 및 Constructor, toString() 까지 추가한다.


Serializable 인터페이스 implements 하기

직렬화를 하려면, 우선 Serializable 인터페이스를 implements 해야한다.

import java.io.Serializable;

class Account implements Serializable{}

직렬화 제외하기 - transient

직렬화에서 제외하는 방법은 transient라는 키워드를 사용하면 된다.

그러면 직렬화에서 빠지게 되어 파일에 저장되지 않는다.

[Example]

class Account implements Serializable{

	//... 생략 ...
	private Date reg_date;
	private transient String password; 
    
	public Account(String email,String name,String address,String phone) {
		//...생략...
		reg_date=new Date();
		password="12341234";
	}
	//...생략...
}

2) 객체 쓰기 읽기

2-1) 객체 쓰기(ObjectOutputStream)

객체를 쓰려면 Stream을 열어야 한다.

당장 파일에다가 그 객체를 쓰기 때문에 FileOutputStream을 사용하고,
이 파일 스트림에 객체를 쓸 것이므로 ObjectOutputStream을 사용한다.

Main.java 파일 생성 후, 코드 작성

여기서 user.acc는 우리가 객체를 저장할 파일 이름이다.

파일을 열 때, FileNotFoundException이라는 IOException이 발생할 수 있기 때문에, main 함수에서 throws로 처리한다.

Account user = new Account("reakwon@aaa.ccc","reakwon","seoul","010-1234-1010"); 를 통해 파일에 써줄 객체를 정의한 뒤,

oss.wirteObject(user)을 통해
ObjectOutputStream의 객체 쓰기 메소드인 writeObject에 전달해준다.

[결과]

중간에 잘리고 알아볼 수 없는 문자들도 있지만, 멤버의 필드들만 보이고 메소드의 구현부는 확인할 수 없다.


2-2) 객체 읽기(ObjectInputStream)

user.acc 파일에 쓰여진 객체를 읽어보자.

객체를 읽는 데는 파일 읽기 스트림(FileInputStream)을 열고, ObjectInputStream을 통해서 읽어오면 된다.

    Account ruser = null;
    FileInputStream fis = new FileInputStream("user.acc");
    ObjectInputStream ois = new ObjectInputStream(fis);

    ruser = (Account) ois.readObject();

    System.out.println(ruser);

    ois.close();

코드를 main에 추가한다.

ois.readObject() 에서 객체의 클래스를 찾을 수없는 예외인 ClassNotFoundException이 발생할 수 있으므로, 메인 메소드에서 예외처리를 해준다.

ctrl + . 을 누르면 어떻게 오류를 해결할지 VS code에서 알려준다.

예외처리 성공, F5 눌러서 실행

[결과]

객체를 제대로 읽어왔다 !


출처 : https://reakwon.tistory.com/160

profile
진주의 코딩일기

0개의 댓글