고급JAVA 12강 - 보조스트림과 직렬화

Whatever·2021년 11월 15일
0

고급 JAVA

목록 보기
12/32

3.2 BufferedInputStream과 BufferedOutputStream

  • 입출력 효율을 높이기 위해 버퍼(byte[])를 사용하는 보조스트림
  • 보조스트림을 닫으면 기반스트림도 닫힌다.

bout.flush(); // 작업을 종료하기 전에 버퍼에 남아있는 데이터를 모두 출력 시킨다.

버퍼를 사용하면 전체적인 속도가 향상된다.

3.3 DataInputStream과 DataOutputStream

  • 기본형 단위로 읽고 쓰는 보조스트림
  • 각 자료형의 크기가 다르므로 출력할 때와 입력할 때 순서에 주의

5.1 BufferedReader와 BufferedWriter

  • 입출력 효율을 높이기 위해 버퍼(char[])를 사용하는 보조스트림
  • 라인(line)단위의 입출력이 편리하다.

7.1 직렬화(serialization)란?

  • 객체를 ‘연속적인 데이터’로 변환하는 것. 반대과정은 ‘역직렬화’라고 한다.

  • 객체의 인스턴스변수들의 값을 일렬로 나열하는 것

  • 객체를 저장하기 위해서는 객체를 직렬화해야 한다.

  • 객체를 저장한다는 것은 객체의 모든 인스턴스변수의 값을 저장하는 것

7.2 ObjectInputStream, ObjectOutputStream

  • 객체를 직렬화하여 입출력할 수 있게 해주는 보조스트림
  • 객체를 파일에 저장하는 방법
  • 파일에 저장된 객체를 다시 읽어오는 방법

7.3 직렬화 가능한 클래스 만들기(1/2)

  • java.io.Serializable을 구현해야만 직렬화가 가능하다. - Serializable인터페이스에는 아무것도 없다.
  • 제어자 transient가 붙은 인스턴스변수는 직렬화 대상에서 제외된다.
  • Serializable을 구현하지 않은 클래스의 인스턴스도 직렬화 대상에서 제외
    transient라는 단어가 붙으면 그 변수값은 직렬화 대상에서 제외됨
    => 데이터가 아예 저장되지 않는 것은 아님, 변수형 자료형의 기본값이 저장됨

7.3 직렬화 가능한 클래스 만들기(2/2)

  • Serializable을 구현하지 않은 조상의 멤버들은 직렬화 대상에서 제외된다.
  • readObject()와 writeObject()를 오버라이딩하면 직렬화를 마음대로…

7.4 직렬화 가능한 클래스의 버전관리

  • 직렬화했을 때와 역직렬화했을 때의 클래스가 같은지 확인할 필요가 있다.
  • 직렬화할 때, 클래스의 버전(serialVersionUID)을 자동계산해서 저장한다.
  • 클래스의 버전을 수동으로 관리하려면, 클래스 내에 정의해야 한다.
  • serialver.exe는 클래스의 serialVersionUID를 자동생성해준다.

Buffered Stream

public class BufferedIOTest01 {

public static void main(String[] args) {
	// 입출력의 성능 향상을 위해서 Buffered스트림을 사용한다.
	
	try {
		FileOutputStream fout = new FileOutputStream("d:/d_other/bufferTest.txt");
		
		// 버퍼의 크기가 5일 버퍼스트림 객체 생성
		// 버퍼의 크기를 정하지 않으면 8KB(8192bytes)의 크기로 설정된다.
		BufferedOutputStream bout = new BufferedOutputStream(fout, 5);
		
		for(char ch ='1'; ch <='9'; ch++) {
			bout.write(ch);
		}
		
		bout.flush(); // 작업을 종료하기 전에 버퍼에 남아있는 데이터를 모두 출력 시킨다.
		System.out.println("출력 작업 끝...");
		
		bout.close(); // 스트림 닫기 
              ==> 보조 스트림을 닫으면 보조 스트림이 사용하는 기반이 되는 스트림도 같이 닫힌다.
		
	} catch (IOException e) {
		// TODO: handle exception
	}

}

}

public class BufferedIOTest02 {

public static void main(String[] args) {
	// 문자 기반의 Buffered 스트림 사용 예제
	try {
		
		//이클립스에서의 자바 프로그램이 실행되는 현재 위치는 해당 프로젝트 폴더가 현재 위치가 된다.
		FileReader fr = new FileReader("./src/kr/or/ddit/basic/FileTest01.java");
		BufferedReader br = new BufferedReader(fr);
		
		String temp = "";
		
		for(int i = 1; (temp=br.readLine()) !=null; i++) {//읽어오는 값이 null이 아닐때까지
			System.out.printf("%4d : %s\n" , i , temp); 
			//%d는 숫자를 입력하라는 뜻, %4d => 자릿수 4자리의 숫자를 넣을 공간 확보 
		}
		
		br.close();
		
	} catch (IOException e) {
		// TODO: handle exception
	}

}

}

ObjectInput / Output Stream

public class ObjectIOTest {

public static void main(String[] args) {
	// Member의 인스턴스 생성
	Member mem1 = new Member("홍길동", 20, "대전");
	Member mem2 = new Member("홍길서", 30, "서울");
	Member mem3 = new Member("홍길남", 40, "인천");
	Member mem4 = new Member("홍길북", 50, "강릉");

	try {
		//객체를 파일에 저장하기
		FileOutputStream fout = new FileOutputStream("d:/d_other/memObj.bin");
		BufferedOutputStream bout = new BufferedOutputStream(fout);
		ObjectOutputStream oout = new ObjectOutputStream(bout);
		
		//쓰기 작업 시작
		System.out.println("객체 저장하기 시작...");
		oout.writeObject(mem1);
		oout.writeObject(mem2);
		oout.writeObject(mem3);
		oout.writeObject(mem4);
		System.out.println("객체 저장 작업 끝...");
		
		oout.close(); //스트림 닫기
	} catch (IOException e) {
		// TODO: handle exception
	}
		
		//======================================================
		
		//저장된 객체를 읽어와 그 내용을 화면에 출력하기
		
	try {
		//입력용 스트림 객체 생성
		ObjectInputStream oin = new ObjectInputStream(
				new BufferedInputStream(
						new FileInputStream("d:/d_other/memObj.bin")
				)
			);
		
		Object obj; //읽어온 객체를 저장할 변수
		
			System.out.println("객체 읽기 작업 시작...");
			
			// readObject()메서드가 데이터를 끝까지 다 읽어오면 EOFException이 발생
			
			while((obj = oin.readObject())!=null) {
				//읽어온 데이터를 원래의 객체형으로 변환 후 사용한다.
				Member mem = (Member)obj;
				
				System.out.println("이름 : " + mem.getName());
				System.out.println("나이 : " + mem.getAge());
				System.out.println("주소 : " + mem.getAddr());
				System.out.println("----------------------------------");
				
			}
		} catch (EOFException e) {

			System.out.println("객체 읽기 작업 끝...");
			
		} catch (ClassNotFoundException e) {
			// TODO: handle exception
		} catch (IOException e) {
			
		}
		

}

}

class Member implements Serializable{

private static final long serialVersionUID = 562285606573703211L;

// transient ==> 직력화가 되지 않을 멤버변수에 지정한다.
// 직렬화가 되지 않은 멤버변수는 기본값으로 저장된다.
// (참조변수 ==> null, 숫자유형변수 => 0)

private String name;
private transient int age;
private String addr;

public Member(String name, int age, String addr) {
	this.name = name;
	this.age = age;
	this.addr = addr;
}

public String getName() {
	return name;
}

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

public int getAge() {
	return age;
}

public void setAge(int age) {
	this.age = age;
}

public String getAddr() {
	return addr;
}

public void setAddr(String addr) {
	this.addr = addr;
}

}

Dialog

public class DialogTest {

public static void main(String[] args) {
	// SWING의 파일 열기, 저장 창 연습
	JFileChooser chooser = new JFileChooser();
	
	//선택할 파일의 확장자 설정
	FileNameExtensionFilter doc = new FileNameExtensionFilter("Word File","docx", "doc");
	FileNameExtensionFilter img = new FileNameExtensionFilter("Image File", new String[] {"png", "jpg", "gif"});
	FileNameExtensionFilter txt = new FileNameExtensionFilter("text파일(.txt)","txt");
	
	chooser.addChoosableFileFilter(doc);
	chooser.addChoosableFileFilter(img);
	chooser.addChoosableFileFilter(txt);

	// 확장자 목록 중 기본적으로 선택될 확장자 지정
	chooser.setFileFilter(txt); 
	
	// 모든 파일 목록 표시 여부 설정(trie: 설정 false: 해제)

// chooser.setAcceptAllFileFilterUsed(false);
chooser.setAcceptAllFileFilterUsed(true);

	// Dialog창에 나타날 기본 경로 설정하기
	chooser.setCurrentDirectory(new File("d:/d_other"));
	
	// 열기 창 
	int result = chooser.showOpenDialog(new JPanel());
	
	// 저장 창
	//int result = chooser.showSaveDialog(new Panel());
	
	// '열기 창' 또는 저장 창에서 선택한 파일 정보 가져오기 
	
	//'열기' 또는 '저장'버튼을 눌렀을 경우에는...
	if(result == JFileChooser.APPROVE_OPTION) { // '열기'
		//선택한 파일 정보 구하기
		File selectedFile = chooser.getSelectedFile();
		System.out.println("선택한 파일 : " + selectedFile.getAbsolutePath());
	}
	
}

}

DialogFileCopy

public class DialogFileCopyTest {

enum DialogChoice{ OPEN, SAVE };
public static void main(String[] args) {
	
	new DialogFileCopyTest().fileCopyStart();
}

public void fileCopyStart() {
	//복사할 원본 파일 선택
	File file = showDialog(DialogChoice.OPEN);
	if(file == null) {
		System.out.println("복사할 원본 파일을 선택하지 않았습니다.");
		System.out.println("복사 작업을 중단합니다.");
		return;
	}
	
	if(!file.exists()) {//파일이 없으면
		System.out.println(file.getPath() + "파일이 없습니다.");
		System.out.println("복사 작업을 중단합니다.");
		return;
	}
	
	//복사될 대상 파일 선택
	File targetFile = showDialog(DialogChoice.SAVE);
	if(targetFile==null) {
		System.out.println("복사할 원본 파일을 선택하지 않았습니다.");
		System.out.println("복사 작업을 중단합니다.");
		return;
	}
	
	if(targetFile.exists()) {//'연습용' 폴더가 없으면
		targetFile.mkdir(); //'연습용' 폴더를 만든다.
		
	}
	
	try {
		//복사할 원본 파일에 사용할 스트림객체 생성
		FileInputStream fin = new FileInputStream(file);
		
		//복사될 대상 파일에 사용할 스트림객체 생성
		FileOutputStream fout = new FileOutputStream(targetFile);
		
		System.out.println("복사 시작...");
		
		int data; //읽어온 데이터가 저장될 변수
		
		while((data=fin.read())!=-1) {
			fout.write(data);
		}
		
		//스트림 닫기
		fin.close();
		fout.close();
	} catch (Exception e) {
		// TODO: handle exception
	}
	
}

public File showDialog(DialogChoice choice) {
	// SWING의 파일 열기, 저장 창 연습
			JFileChooser chooser = new JFileChooser();
			
			//선택할 파일의 확장자 설정

// FileNameExtensionFilter doc = new FileNameExtensionFilter("Word File","docx", "doc");
// FileNameExtensionFilter img = new FileNameExtensionFilter("Image File", new String[] {"png", "jpg", "gif"});
// FileNameExtensionFilter txt = new FileNameExtensionFilter("text파일(.txt)","txt");
//
// chooser.addChoosableFileFilter(doc);
// chooser.addChoosableFileFilter(img);
// chooser.addChoosableFileFilter(txt);

			// 확장자 목록 중 기본적으로 선택될 확장자 지정

// chooser.setFileFilter(txt);

			// 모든 파일 목록 표시 여부 설정(trie: 설정 false: 해제)

// chooser.setAcceptAllFileFilterUsed(false);
chooser.setAcceptAllFileFilterUsed(true);

			// Dialog창에 나타날 기본 경로 설정하기
			chooser.setCurrentDirectory(new File("d:/d_other"));
			
			int result = -1;
			if(choice == DialogChoice.OPEN) {
				// 열기 창 
				result = chooser.showOpenDialog(new JPanel());
				
			}else {
				// 저장 창
				result = chooser.showSaveDialog(new JPanel());
			}
			
			File selectedFile = null;
			//'열기' 또는 '저장'버튼을 눌렀을 경우에는...
			if(result == JFileChooser.APPROVE_OPTION) { // '열기'
				//선택한 파일 정보 구하기
				selectedFile = chooser.getSelectedFile();
				System.out.println("선택한 파일 : " + selectedFile.getAbsolutePath());
			}
	return selectedFile;
}

}

0개의 댓글