본문 바로가기
Java/Java

자바입출력/byte기반) 객체를 대상으로한 입출력 (ObjectInputStream, ObjectOutputStream)

by 박채니 2022. 3. 29.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


자바 입출력(java IO)

- 프로그램을 기준으로 외부로부터 데이터가 들어오는 입력(input)과 프로그램에서 외부로 나가는 출력(output)으로 구성

- 입력의 대상 : 키보드/마우스/파일/네트워크 등

- 출력의 대상 : 화면/프린터/파일/네트워크/콘솔 등

 

자바 입출력 종류

① byte 단위 입출력

  - 송수신하고자 하는 데이터를 byte 단위로 쪼개 보내고 받는 것

② char 단위 입출력

  - 텍스트 전송에 특화된 방법

 

 


객체 기반 입출력 스트림

 

ObjectInputStream, ObjectOutputStream의 읽기/쓰기 대상이 되는 클래스

- Serializable 인터페이스를 구현 (입출력할 때 실제 데이터를 직렬화 처리에 필요한 인터페이스)

- 클래스 고유의 id값을 작성해야 함(JVM 타입 비교용) -> 1L로 고정

- 메모리 상 관리되는 객체의 필드 중 입출력 스트림에 제외 시키고 싶은 필드transient 키워드 사용

public class User implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private String id;
	private String password;
	private int point;
	private Date regDate;
	
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	public User(String id, String password, int point, Date regDate) {
		super();
		this.id = id;
		this.password = password;
		this.point = point;
		this.regDate = regDate;
	}

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public int getPoint() {
		return point;
	}
	public void setPoint(int point) {
		this.point = point;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", password=" + password + ", point=" + point + ", regDate=" + regDate + "]";
	}
}

 

 

☞ ObjectOutputStream

- 객체를 읽어와서 객체로 출력

 

  1. User[] 에서 User객체를 관리
 2. 객체출력스트림을 이용해 User객체를 하나씩 users.ser파일에 출력

User[] users = new User[3];
users[0] = new User("honggd", "1234", 1000, new Date());
users[1] = new User("sinsa", "1234", 2000, new Date());
users[2] = new User("sejong", "1234", 3000, new Date());
		
File dest = new File("object/users.ser");
		
try(
	ObjectOutputStream oos = 
	new ObjectOutputStream(new FileOutputStream(dest));
) {
	for(User user : users) {
		oos.writeObject(user);
		System.out.println(user.getId() + " 쓰기 완료!");
	}
} catch(IOException e) {
	e.printStackTrace();
}

@콘솔출력값
honggd 쓰기 완료!
sinsa 쓰기 완료!
sejong 쓰기 완료!

파일 생성

writeObject() 메소드를 이용하여 User 객체를 출력하여 object/users.ser 파일에 썼습니다.

 

 

☞ ObjectInputStream

- 객체를 읽어와서 객체 입력

 

1. Users.ser파일을 대상으로 하는 객체 입력 스트림 생성
 2. 한번에 하나의 User객체를 읽어와서 User[]에 추가!

User[] users = new User[100];
File file = new File("object/users.ser");
		
try(ObjectInputStream ois = 
	new ObjectInputStream(new FileInputStream(file));
) {
	for(int i = 0; i < users.length; i++) {
		User user = (User)ois.readObject();	//반환타입이 Object라서 반드시 다운캐스팅 필요
		System.out.println(user.getId() + " 가져오기 완료!");
		users[i] = user;
	}
} catch(EOFException e) {
	//End Of File 파일의 끝의 도달했는데 또 읽으려고 한 경우
	//파일에 존재하는 모든 객체를 읽은 경우
	for(User user : users) {
		if(user == null)
			break;
		System.out.println(user);
	}
} catch(IOException e) {
	e.printStackTrace();
} catch(ClassNotFoundException e) {
	//읽어온 객체의 클래스를 찾지 못한 경우
	e.printStackTrace();
}

@콘솔출력값
honggd 가져오기 완료!
sinsa 가져오기 완료!
sejong 가져오기 완료!
User [id=honggd, password=1234, point=1000, regDate=Tue Mar 29 20:35:15 KST 2022]
User [id=sinsa, password=1234, point=2000, regDate=Tue Mar 29 20:35:15 KST 2022]
User [id=sejong, password=1234, point=3000, regDate=Tue Mar 29 20:35:15 KST 2022]

 

1. userArray.ser파일을 대상으로 하는 객체 출력 스트림 생성
2. User[]을 한 번 출력(소속된 User객체 모두 출력됨)

User[] users = new User[3];
users[0] = new User("honggd", "1234", 1000, new Date());
users[1] = new User("sinsa", "1234", 2000, new Date());
users[2] = new User("sejong", "1234", 3000, new Date());
				
File dest = new File("object/userArray.ser");
		
//쓰기
//1. 스트림 객체 생성
try(ObjectOutputStream oos = 
		new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
) {
	//2. 쓰기 작업
	oos.writeObject(users);
	System.out.println("User[] 쓰기 완료!");
} catch(IOException e) {
	e.printStackTrace();
}
		
//읽기
//1. 스트림 객체 생성
try(ObjectInputStream ois =
		new ObjectInputStream(new BufferedInputStream(new FileInputStream(dest)));
) {
	//2. 읽기 작업
	User[] other = (User[])ois.readObject();
	System.out.println("User[] 읽기 완료!");
	
	//3. 내용 확인
	for(int i = 0; i < other.length; i++) {
		System.out.println(other[i]);
		}
} catch(IOException | ClassNotFoundException e) {
	e.printStackTrace();
} 

@콘솔출력값
User[] 쓰기 완료!
User[] 읽기 완료!
User [id=honggd, password=1234, point=1000, regDate=Tue Mar 29 21:37:19 KST 2022]
User [id=sinsa, password=1234, point=2000, regDate=Tue Mar 29 21:37:19 KST 2022]
User [id=sejong, password=1234, point=3000, regDate=Tue Mar 29 21:37:19 KST 2022]

파일 생성

 

☞ transient 키워드

password 필드 입출력에서 제외!

private transient String password;	//출력스트림 사용 시 값이 있어도 null로 처리

@콘솔출력값
User[] 쓰기 완료!
User[] 읽기 완료!
User [id=honggd, password=null, point=1000, regDate=Tue Mar 29 21:43:31 KST 2022]
User [id=sinsa, password=null, point=2000, regDate=Tue Mar 29 21:43:31 KST 2022]
User [id=sejong, password=null, point=3000, regDate=Tue Mar 29 21:43:31 KST 2022]

입출력 스트림에 제외시키고 싶은 필드가 있다면 transient 키워드를 사용하여 null 값으로 표현해줍니다.