데이터 직렬화 (Serialize)
*데이터 직렬화는
1. 객체를 저장하는 경우
2. 데이터를 DB에 올리는 경우
3. 파일을 작성하는 경우
4. 파싱할 데이터를 통신하는 경우
등 여러가지 케이스에 유의미한 데이터를 저장해두기 위해 사용한다.
*유의미한 데이터 : 값(value)을 가지고 있다.
*무의미한 데이터 : 참조변수. 유의미한 데이터의 주소(address)를 가지고 있다.
-> 데이터가 값의 주소를 가지고 있는 경우, 데이터를 사용하려고 할 때
해당 데이터의 주소는 바뀌어 의미를 잃었을 가능성이 크다.
또한 String 형식의 값이 참조변수로 구현되어 있는 경우,
다른 형식들과는 다르게 메모리가 순서대로 배열되어 있지 않다.
따라서 직렬화가 필요하다. == 연속적인 데이터로 변환하는 과정이 필요하다.
== 스트림으로 변환하는 과정이 필요하다.
*여기서 스트림(Stream)이란
: 자바에서는 입출력을 스트림으로 처리하는데,
데이터의 연속적 배열을 의미하며 데이터를 보관할 경우 데이터 형식을 변환할 때 이용한다.
이를 이용하여 파일에 저장할 경우 데이터를 영구히 보관할 수 있다.
스트림은 단방향이며 선입선출 구조이다. 또한 연결 및 지연 될 수 있다.
-> 읽을 데이터가 없다면 생길 때까지 대기하고, 데이터가 꽉 차 있다면 순서가 될 때까지 대기한다.
*스트림의 종류
1. 바이트 스트림
: 바이트(8비트)의 입출력 시 이용
(InputStream, OutputStram 클래스와 그의 하위 클래스 이용함
주요 메서드 : abstract int read(), abstract void write(int byte) *한 바이트 단위 입출력 )
문자 데이터와 바이너리 데이터에 관계없이 이용할 수 있음
2. 문자 스트림
: 16비트 형식의 문자나 문자열의 입출력 시 이용
(Reader, Writer 클래스와 그의 하위 클래스 이용함
주요 메서드 : abstract int read(), abstract void write(int byte) *한 문자 단위 입출력 )
문자가 아닌 데이터에 적용할 경우 정상적으로 처리하지 못함 (깨짐 현상 발생)
*데이터 직렬화 예제
데이터를 직렬화 하려면 해당 데이터 클래스에 java.io.Serializable 인터페이스를 상속받아야 한다.
import java.io.Serializable;
public class Fruit implements Serializable {
private String taste;
private String color;
private int number;
public Fruit(String taste, String color,int number){
this.taste = taste;
this.color = color;
this.number = number;
}
public String getTaste() {
return taste;
}
public void setTaste(String taste) {
this.taste = taste;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
import android.os.Build;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Base64;
import androidx.annotation.RequiresApi;
public class PracticeActivity {
@RequiresApi(api = Build.VERSION_CODES.O)
public void main(String[] args){
convertSerializedData();
convertJson();
}
/**JAVA format*/
@RequiresApi(api = Build.VERSION_CODES.O)
public void convertSerializedData(){
Fruit fruit = new Fruit("sweet","yellow",1);
byte[] serializedData = new byte[0];
/**데이터 직렬화 과정*/
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
objectOutputStream.writeObject(fruit);
serializedData = byteArrayOutputStream.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
/**직렬화 된 데이터 serializedData를 출력함*/
System.out.println(Base64.getEncoder().encodeToString(serializedData));
}
/**JSON format*/
public void convertJson(){
Fruit fruit = new Fruit("sweet","yellow",1);
String json = String.format(
"{\"taste\":\"%s\",\"color\":\"%s\",\"number\":%d}",
fruit.getTaste(), fruit.getColor(), fruit.getNumber());
System.out.println(json);
}
}
나는 데이터 통신 시에 직렬화를 가장 많이 사용하기 때문에
InputStream 과 OutputStream을 이용한 직렬화 외에도 JSON형태로 직렬화 하는 경우를 추가로 정리한다.
(이외에도 XML, CSV 형태가 있다.)
이렇게 직접 JSON 문자열을 작성하는 경우는 거의 없긴 하다.
다만 APP끼리의 통신에서 직렬화 데이터의 전달 및 수신이 필요한 경우가 있는데,
그런 케이스에는 아래와 같이 통신하여 사용한다.
/**직렬화 데이터 전달*/
bundle.putSerializable("KEY","VALUE");
intent.putExtras(bundle)
/**직렬화 데이터 수신*/
Serializable data = bundle.getSerializableExtra("dataset");
FruitData fruitData = (FruitData)data;
데이터 직렬화가 필요한 경우에 직렬화를 하지 않을 경우 (Serializable 인터페이스를 상속받지 않는 경우),
RuntimeException 등이 발생할 수 있다.
'JAVA > Android' 카테고리의 다른 글
[JAVA][Android] JSON / GSON / JACKSON (0) | 2022.07.21 |
---|---|
[JAVA][Android] ActivityResultLauncher를 이용한 액티비티 간의 통신 (0) | 2022.07.20 |
[JAVA][Android] 액티비티 종료 전 주요 데이터를 Bundle에 저장하여 재활용하기 (0) | 2022.06.21 |
[JAVA][Android] ImageView 영역에 원하는 radius값을 반영하는 setOutlineProvider (0) | 2022.06.21 |
[JAVA][Android] ProgressBar 디자인 java 코드로 변경하기 (+ 변경 시 비가시화 처리 되는 현상 해결방법) (0) | 2022.05.26 |