Notice
Recent Posts
Recent Comments
Link
passion and relax
[JAVA] 14. 객체 저장 (직렬화와 입출력) 본문
데이터의 저장
행동은 클래스 안에 들어가지만, 상태는 각 객체 안에서 산다.
직렬화 저장과 일반 텍스트 파일 저장의 두가지 방법이 있다.
직렬화
각 객체의 상태를 저장하는 것
직렬화 하면 인스턴스 변수 객체 또 그 객체의 인스턴스 변수 객체, ... 이들 모두가 직렬화 되어 저장된다.
(단, 해당 객체를 implements Serializable 해야 한다)
직렬화 대상 객체가 상속되어 있다면, 최상위만 implements Serializable 하면 된다. 상속 이니깐 그렇다.
정적 변수는 직렬화되지 않는다. 따라서 정적 변수는 잘 써야 한다. 저장이 안되어도 괜찮도록..
Connection Stream (연결 스트림) VS Chain Stream (연쇄 스트림)
Connection Stream
. 출발지 또는 목적지로의 연결
. byte 저장을 하는 등 대부분 저수준이다.
. 예) FileOutputStream : 파일로 byte를 저장 해준다.
Chain Stream
. Object 저장과 같은 고수준으로 끌어 올릴 때 사용하는 stream
. 출발지 또는 목적지와 무관하게 단지 그 단위를 높여 준다.
. 예) ObjectOutputStream : 객체를 스트림으로 보낼 수 있도록 데이터 형태를 변경해 준다.
* chain stream은 혼자서는 연결될 수 없다. 반드시 connection stream에 chain 되어야 한다.
직렬화 객체 저장 및 불러오기
public class GameSaverTest {
public static void main(String[] args) {
GameCharacter one = new GameCharacter(10, "aaa", new String[] {"a-1", "a-2", "a-3"});
GameCharacter two = new GameCharacter(20, "bbb", new String[] {"b-1", "b-2", "b-3"});
GameCharacter thr = new GameCharacter(30, "ccc", new String[] {"c-1", "c-2", "c-3"});
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("Game.ser"));
os.writeObject(one);
os.writeObject(two);
os.writeObject(thr);
os.close();
} catch (Exception ex) {
Logger.getLogger(GameSaverTest.class.getName()).log(Level.SEVERE, null, ex);
}
one = two = thr = null;
try {
ObjectInputStream is = new ObjectInputStream(new FileInputStream("Game.ser"));
GameCharacter oneRestore = (GameCharacter) is.readObject();
GameCharacter twoRestore = (GameCharacter) is.readObject();
GameCharacter thrRestore = (GameCharacter) is.readObject();
System.out.println(oneRestore.getType());
System.out.println(twoRestore.getType());
System.out.println(thrRestore.getType());
} catch (Exception ex) {
Logger.getLogger(GameSaverTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class GameCharacter implements Serializable {
transient String currId; //저장에서 제외해야 한다면, 실행 중에 결정되는 요소라면, transient
int power;
String type;
String[] weapones;
public GameCharacter(int power, String type, String[] weapones) {
this.power = power;
this.type = type;
this.weapones = weapones;
}
public int getPower() {
return power;
}
public String getType() {
return type;
}
public String getWeapones() {
String weaponList = "";
for (int i=0; i<weapones.length; i++) {
weaponList += weapones[i] + " ";
}
return weaponList;
}
}
텍스트 파일로 저장 및 불러오기
public class WriteAFile {
public static void main(String[] args) {
try {
FileWriter writer = new FileWriter("Foo.txt");
writer.write("hello foo!");
writer.close();
} catch (Exception ex) {
Logger.getLogger(WriteAFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
java.io.File
파일의 내용이 아닌 파일 또는 디렉토리 자체를 위한 클래스. 즉, 파일 읽기/쓰기와는 무관하다.
File 객체 만들기 및 새 디렉토리 생성
File f = new File ("MyCode.txt"); //File 객체 만들기
File dir = new File ("Chapter 7"); //디렉토리용 File 객체 만들기
dir.mkdir(); //디렉토리용 File 객체로 새 디렉토리 만들기
String[] dirContents = dir.list(); //디렉토리 내의 목록 담기
dir.getAbsolutePath(); //파일 또는 디렉토리의 절대 경로
f.delete(); //파일 또는 디렉토리의 삭제
Buffer
new FileWriter (aFile); 이것만 쓰면, 문자열 마다 파일에 write 하게 된다. 즉, 느리다.
new BufferedWriter (aFileWriter); 버퍼에 담았다가 write 하도록, BufferedWriter와 chaining 해준다.
BufferedWriter writer = new BufferWriter (new FileWriter(file));
writer.write("haha");
writer.write("hoho");
버퍼에 가득차서 자동으로 보내기 전에 지금 당장 보내고 싶다면 writer.flush();
텍스트 저장 파일 읽기
FileReader라는 "텍스트 파일로 연결되는 문자를 위한 연결 스트림"을 이용한다.
public class ReadAFileText {
public static void main(String[] args) {
try {
File myFile = new File("Foo.txt");
FileReader fileReader = new FileReader(myFile);
BufferedReader reader = new BufferedReader(fileReader);
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (IOException ex) {
Logger.getLogger(ReadAFileText.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
QuizCardBuilder 와 QuizCardPlayer
QuizCardBuilder : p.484
QuizCordPlayer : p.490
버전 ID (SerialVersion UID)
저장한 시점의 객체 버전과 불러오는 시점의 객체 버전이 맞아야 하는데, 이를 위한 것.
클래스의 구조에 대한 정보를 바탕으로 serialVersion UID가 생성된다.
즉, 클래스 구조가 바뀌면 이 serialVersion UID가 변경되어 저장한 시점의 객체 버전과 불러오는 시점의 객체 버전을 확인할 수 있다.
이 버전이 맞지 않으면 읽어오기에서 에러 발생
'프로그래밍' 카테고리의 다른 글
[JAVA] 16. 자료구조 (컬렉션 및 제네릭) (0) | 2024.06.04 |
---|---|
[JAVA] 15. 연결하는 방법 (네트워크 소켓과 멀티스레딩) (0) | 2024.06.04 |
[JAVA] 13. 스윙을 알아봅시다 (레이아웃 관리와 구성요소) (0) | 2024.05.30 |
[JAVA] 12. 그래픽 이야기 (GUI, 이벤트 처리, 내부 클래스에 대한 소개) (0) | 2024.05.28 |
[JAVA] 11. 위험한 행동 (예외 처리) (0) | 2024.05.27 |