Decorator 패턴을 이용해서 파일 I/O를 더 쉽게 출력해보자
📌 DataOutputStream을 사용해보자
- 게시글 출력
// 게시글 데이터를 파일로 내보내기(저장하기, 쓰기)
try (
// 파일에 바이트를 출력하는 객체
FileOutputStream out = new FileOutputStream("board.data");
DataOutputStream out2 = new DataOutputStream(out)) {
// 출력할 게시글 개수를 먼저 저장한다.
out2.writeInt(boardList.size());
for (Board board : boardList) {
// 1) 게시글 번호 4바이트 출력
out2.writeInt(board.getNo());
// 2) 게시글 제목 출력
out2.writeUTF(board.getTitle());
// 3) 게시글 내용 출력
out2.writeUTF(board.getContent());
// 4) 게시글 등록일 출력
out2.writeUTF( board.getRegisteredDate().toString());
// 5) 게시글 조회수 출력
out2.writeInt(board.getViewCount());
// 6) 게시글 작성자 번호 출력
out2.writeInt(board.getWriter().getNo());
// 7) 게시글 작성자 이름 출력
out2.writeUTF(board.getWriter().getName());
}
System.out.println("게시글 저장 완료!");
} catch (Exception e) {
System.out.println("게시글을 파일에 저장 중 오류 발생!");
}
- 게시글 저장
// 파일에서 게시글 데이터를 가져오기(로딩하기, 읽기)
// => 저장할 때 사용한 규칙에 따라 읽어야 한다.
// => 즉 파일 포맷에 맞춰 읽는다.
try (
// 파일에서 바이트를 읽어 오는 일을 하는 객체
FileInputStream in = new FileInputStream("board.data");
// 읽어온 바이트를 가공하여 primitive 타입의 값이나 String 객체로 가공하는 일을 하는 객체
DataInputStream in2 = new DataInputStream(in); ) {
int size = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
for (int i = 0; i < size; i++) {
Board board = new Board();
// 1) 게시글 번호 읽기
board.setNo(in2.readInt()); // writerInt()로 출력한 데이터를 읽을 때 사용
// 2) 게시글 제목 읽기
board.setTitle(in2.readUTF()); // writerUTF()로 출력한 데이터를 읽을 때 사용
// 3) 게시글 내용 읽기
board.setContent(in2.readUTF());
// 4) 게시글 등록일 읽기
board.setRegisteredDate(Date.valueOf(in2.readUTF()));
// 5) 게시글 조회수 읽기
board.setViewCount(in2.readInt());
// 6) 작성자 정보 읽기
Member writer = new Member();
// - 작성자 번호 읽기
writer.setNo(in2.readInt());
// - 작성자 이름 읽기
writer.setName(in2.readUTF());
// - 게시글에 작성자 정보 저장
board.setWriter(writer);
// 목록에 게시글 저장
boardList.add(board);
}
System.out.println("게시글 로딩 완료!");
} catch (Exception e) {
System.out.println("파일에서 게시글을 읽어 오는 중 오류 발생!");
}
}
📌 serialize
implements Serializable : 직렬화 할 수 있어요 표시 / 인터페이스 안에 아무것도 없다.
[직렬화]
@SuppressWarnings("serial")
public class Board implements Serializable {
private int no;
private String title;
private String content;
private Member writer;
private Date registeredDate;
private int viewCount;
private int like;
📌 ObjectOutputStream을 사용해보자
[출력]
try (
// 파일에 바이트를 출력하는 객체
FileOutputStream out = new FileOutputStream("board.data2");
// 출력할 객체의 모든 필드 값을 바이트 배열에 담는 일을 하는 객체
ObjectOutputStream out2 = new ObjectOutputStream(out)) {
// 출력할 게시글 개수를 먼저 저장한다.
out2.writeInt(boardList.size());
for (Board board : boardList) {
out2.writeObject(board);
}
System.out.println("게시글 저장 완료!");
} catch (Exception e) {
System.out.println("게시글을 파일에 저장 중 오류 발생!");
e.printStackTrace();
}
}
[리팩토링]
// 게시글 데이터를 파일로 내보내기(저장하기, 쓰기)
try (
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("board.data3"))) {
out.writeObject(boardList);
System.out.println("게시글 저장 완료!");
} catch (Exception e) {
System.out.println("게시글을 파일에 저장 중 오류 발생!");
e.printStackTrace();
}
}
[입력]
try (
// 파일에서 바이트를 읽어 오는 일을 하는 객체
FileInputStream in = new FileInputStream("board.data");
// 직렬화 방식으로 출력된 바이트를 읽어 객체의 필드 값으로 복원하는 일을 하는 객체
ObjectInputStream in2 = new ObjectInputStream(in); ) {
int size = in2.readInt();
for (int i = 0; i < size; i++) {
boardList.add((Board)in2.readObject());
}
System.out.println("게시글 로딩 완료!");
} catch (Exception e) {
System.out.println("파일에서 게시글을 읽어 오는 중 오류 발생!");
}
}
[리팩토링]
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("board.data3")); ) {
boardList.addAll((List<Board>) in.readObject());
System.out.println("게시글 로딩 완료!");
} catch (Exception e) {
System.out.println("파일에서 게시글을 읽어 오는 중 오류 발생!");
}
}
📌 어떤 스트림을 쓸 것인지는 판단에 맡긴다.
'Language > Java' 카테고리의 다른 글
🚿 Decorator design patter & stream 2 (0) | 2021.09.19 |
---|---|
🔋 버퍼(buffer)의 필요성을 느껴보자 (0) | 2021.09.13 |
📁 자바에서는 어떻게 파일 입출력을 할까? (0) | 2021.09.07 |
🔒 권한(Authorization)은 어떻게 설정할까요? (0) | 2021.09.03 |
📯 자바 : Command design pattern (0) | 2021.09.02 |