Part 15. 입출력

Hyunsu·2023년 3월 3일
0

국비 교육

목록 보기
20/36
post-thumbnail

벌써 자바 기초 수업이 끝났다.
이제부터는 응용할 수 있도록 연습해야겠다.

📝 목차

  1. 입출력 (IO)
  2. File 클래스
  3. 스트림 클래스
  4. InputStream
  5. OutputStream
  6. Reader
  7. Writer
  8. 보조 스트림
  9. 직렬화와 역직렬화

1. 입출력 (IO)

Input 과 Output 의 약자로 컴퓨터 내부 또는 외부 장치와 프로그램 간의 데이터를 주고 받는 것이다.
장치와 입출력을 위해서는 하드웨어 장치에 직접 접근이 필요한데 다양한 매체에 존재하는 데이터들을 사용하기 위해 입출력 데이터를 처리할 공통적인 방법으로 스트림을 이용한다.

스트림은 데이터가 이동하는 통로라고 생각하면 된다. 양방향인 파이프 스트림을 제외하고 단방향으로만 흘러갈 수 있다.


2. File 클래스

파일 시스템의 파일을 표현하는 클래스이다. 파일 크기와 속성 및 이름 등의 정보와 파일 생성 및 삭제 기능을 제공한다. 본 수업에서는 다루지 않고 넘어갔다.

File file = new File("파일 경로");
File file = new File("C:/dev/test.txt");

파일 또는 디렉토리 생성 및 삭제 메서드

파일 또는 디렉토리 정보 리턴 메서드


3. 스트림 클래스

입출력 장치에서 데이터를 읽고 쓰기 위한 클래스로 모든 스트림은 단방향이며 각각의 장치마다 연결할 수 있는 스트림이 존재한다. 하나의 스트림으로 입출력을 동시에 수행할 수 없으므로 동시에 수행하려면 두 개의 스트림이 필요하다.

숫자와 문자는 1 byte 씩 출력하고 한글은 2 byte 씩 출력한다.
스트림 클래스는 모두 다 외우지는 말고 필요할 때 사용하도록 한다.

다음은 스트림 클래스의 종류이다. 색이 있는 것은 기반 스트림이고 색이 없는 것은 보조 스트림이다.

  • 바이트 기반 스트림 : 1 byte 단위로 데이터를 입출력하는 스트림

얇은 빨대라고 생각하면 된다. 데이터를 잘라서 전송하기 때문에 데이터가 깨질 수 있다. 따라서 이미지나 영상 및 파일 등 문자가 아닌 데이터나 파일 또는 1 byte 문자로 이루어진 텍스트를 전송할 때 사용하는 것이 좋다.

  • 문자 기반 스트림 : 문자 단위로 데이터를 입출력하는 스트림

두꺼운 빨대라고 생각하면 된다. 문자로 이루어진 텍스트나 채팅 및 코드를 전송할 때 사용하는 것이 좋다.

  • 기반 스트림 : 혼자 입출력을 할 수 있는 스트림
  • 보조 스트림 : 보조 역할만 하는 혼자 입출력을 할 수 없는 스트림

스트림 사용 방법은 기본적으로 비슷하므로 패턴을 외워두는 것도 좋다. 경로명 작성에서 상대 경로의 기준은 현재 프로젝트 폴더 내부이다.
private String content = "Hello World\n" + "987654321\n" + "오늘은 금요일\n" + "!@#$%^&*():";

public void byteOutPut() { // 바이트 기반 출력

	// 스트림 참조 변수 선언을 try 전에 한 이유 : finally 에서도 해당 참조 변수를 사용하기 위해
	FileOutputStream fos = null;
	
	try {
    
    	// 프로그램에서 지정된 경로로 파일 내보냄 (출력)
		// 만약 경로 제일 마지막에 작성한 파일이 존재하지 않는다면 출력 구문 수행 시 자동으로 생성됨
		// 파일이나 폴더가 없을 수 있으므로 FileNotFoundException 발생 가능성 존재
		fos = new FileOutputStream("byte/byteTest.txt"); // 이어쓰기 하고 싶으면 true
		
		// content에 작성된 문자를 하나씩 쪼개기
		for (int i=0; i<content.length(); i++) {
			char ch = content.charAt(i);
			fos.write(ch); // 프로그램이 txt 파일에 작성 (출력)
		}
		
		System.out.println("출력 완료");
		
	} catch (FileNotFoundException e) { // 파일 없는 경우
		e.printStackTrace();
        
	} catch (IOException e) { // 문제 있는 경우
		e.printStackTrace();
        
	} finally { // 예외 발생 여부와 관계없이 무조건 수행
    
		try {
        
       		// close() : 스트림 내부 내용을 모두 밀어낸 후 객체가 있을 때만 닫음 (메모리 반환)
			if(fos != null) fos.close(); // NullPointerException 방지
			
		} catch (IOException e) {
			e.printStackTrace();
            
		}
	}
    
}

절대 경로 : 절대적인 기준점을 기준으로 작성 c:\tools\eclipse\
상대 경로 : 현재 위치를 기준으로 작성 byte/byteTest.txt


4. InputStream

바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스이다.

📌 FileInputStream

파일을 바이트 단위로 읽을 때 사용한다. 그림 및 오디오와 비디오 및 텍스트 파일 등 모든 종류의 파일 읽기가 가능하다.
InputStream 의 하위 클래스로 InputStream 과 사용 방법이 동일하다.

FileInputStream 객체가 생성될 때 파일과 직접 연결됨
만약 파일 존재하지 않으면 FileNotFoundException 발생하므로 예외처리 필수

FileInputStream fis = new FileInputStream("C:/dev/text.txt");

5. OutputStream

바이트 기반 출력 스트림의 최상위 클래스로 추상 클래스이다.

📌 FileOutputStream

파일을 바이트 단위로 저장할 때 사용한다. 그림 및 오디오와 비디오 및 텍스트 파일 등 모든 종류의 데이터를 파일로 저장할 수 있다.

FileOutputStream 객체가 생성될 때 파일과 직접 연결됨
만약 파일 존재하지 않으면 자동으로 생성하지만
이미 파일이 존재할 경우 파일을 덮어씀

// 파일 존재하지 않는 경우
FileOutputStream fos = new FileOutputStream("C:/dev/text.txt");

// 기존 파일에 이어서 작성하고 싶을 경우
FileOutputStream fos = new FileOutputStream("C:/dev/text.txt"), true;

6. Reader

문자 기반 입력 스트림의 최상위 클래스로 추상 클래스이다.

📌 FileReader

문자 단위로 텍스트 기반 파일을 읽을 때 사용한다.
텍스트가 아닌 그림 및 오디오와 비디오 등의 파일을 읽기가 불가능하다.
Reader 의 하위 클래스로 Reader 와 사용 방법이 동일하다.

FileReader 객체가 생성될 때 파일과 직접 연결됨
만약 파일 존재하지 않으면 FileNotFoundException 발생하므로 예외처리 필수

FileReader fr = new FileReader("C:/dev/text.txt");
FileReader fr = new FileReader(new File("C:/dev/text.txt"));

7. Writer

문자 기반 출력 스트림의 최상위 클래스로 추상 클래스이다.

📌 FileWriter

문자 단위로 텍스트 기반 파일을 쓸 때 사용한다.
텍스트가 아닌 그림 및 오디오와 비디오 등의 파일은 저장이 불가능하다.
Writer 의 하위 클래스로 Writer 와 사용 방법이 동일하다.

FileWriter 객체가 생성될 때 파일과 직접 연결됨
만약 파일 존재하지 않으면 자동으로 생성하지만
이미 파일이 존재할 경우 파일을 덮어씀

// 파일 존재하지 않는 경우
FileWriter fw = new FileWriter("C:/dev/text.txt");

// 기존 파일에 이어서 작성하고 싶을 경우
FileWriter fw = new FileWriter("C:/dev/text.txt"), true;

8. 보조 스트림

스트림의 기능을 향상시키거나 새로운 기능을 추가하기 위해 사용한다.
보조 스트림은 실제 데이터를 주고 받는 스트림이 아니기 때문에 입출력 처리가 불가능하다. 기반 스트림을 먼저 생성한 후 이를 이용해 보조 스트림을 생성해야 한다.

문자 변환 보조 스트림과 성능 향상 보조 스트림 및 기본 타입 입출력 보조 스트림과 객체 입출력 보조 스트림이 있다.

// 기반 스트림 생성
FileInputStream fis = new FileInputStream("sample.txt");

// 보조 스트림 생성
BufferedInputStream bis = new BufferedInputStream(fis);

// 보조 스트림으로부터 데이터 읽어옴
bis.read();

보조 스트림 사용 시 기반 스트림과 기반이 맞아야 오류가 발생하지 않는다.

📌 문자 변환 보조 스트림

소스 스트림이 바이트 기반 스트림이지만 데이터가 문자일 경우에 사용한다. Reader 와 Writer 는 문자 단위로 입출력을 하므로 데이터가 문자인 경우 바이트 기반 스트림보다 편리하게 사용 가능하다.

InputStreamReader

OutputStreamWriter

📌 성능 향상 보조 스트림

느린 속도로 인해 입출력 성능에 영향을 미치는 입출력 소스를 이용하는 경우에 사용한다.
입출력 소스와 직접 작업하지 않고 데이터를 모아 한꺼번에 작업 하여 실행 성능을 향상시킨다. 즉 입출력 횟수를 줄일 수 있다.

BufferedInputStream

BufferedOutputStream

📌 기본 타입 입출력 보조 스트림

기본 자료형 별 데이터 읽고 쓰기가 가능하도록 기능을 제공한다.
단 입력된 자료형의 순서와 출력될 자료형의 순서는 일치해야 한다.

DataInputStream

DataOutputStream

📌 객체 입출력 보조 스트림

객체를 파일 또는 네트워크로 입출력 할 수 있는 기능을 제공한다.
단 객체는 문자가 아니므로 바이트 기반 스트림으로 데이터를 변경해주는 직렬화가 필수이다.

ObjectInputStream

ObjectOutputStream


9. 직렬화와 역직렬화

  • 직렬화

Serializable 인터페이스는 직렬화가 될 수 있는 객체가 상속 받는 인터페이스이다. ObjectOutputStream 이 객체를 내보낼 때 해당 인터페이스를 상속 받은 객체인 경우에만 직렬화를 진행한다. 컬렉션의 경우 모두 직렬화가 가능하도록 Serializable 인터페이스 구현이 되어있다. 단 컬렉션에 저장하는 객체가 직렬화가 가능하지 않다면 NotSerializableException 이 발생한다.

Serializable 를 상속했지만 구현할 메서드가 없다는 것은 그저 표시 용도의 인터페이스인 마커 인터페이스라는 의미이다.

직렬화 시 private 필드를 포함해 모든 필드를 바이트로 구현하지만 transient 키워드를 사용한 필드는 직렬화에서 제외한다.

  • 역직렬화

직렬화 했을 때와 같은 클래스를 사용한다. 단 클래스 이름이 같더라도 클래스 내용이 변경된 경우 역직렬화를 할 수 없다.

  • serialVersionUID 필드

직렬화한 클래스와 같은 클래스임을 알려주는 식별자 역할로 컴파일 시 JVM 이 자동으로 serialVersionUID 정적 필드를 추가해주기 때문에 별도 작성 하지 않아도 오류는 나지 않지만 자동 생성 시 역직렬화에서 예상치 못한 InvalidClassException 이 발생할 수 있어 명시를 권장한다.

private static final long serialVersionUID = -6423919775137290062L;
profile
현수의 개발 저장소

0개의 댓글