[Java] I/O 패키지

Hyo Kyun Lee·2022년 2월 3일
0

Java

목록 보기
37/49

1. Java 입출력 메소드를 사용하기 위한 I/O 패키지

말 그대로 Input, Output에 대한 클래스와 메소드를 제공해주는 패키지를 일컫는다.

크게 Byte 단위의 입출력과 Char 단위의 입출력을 받는 클래스로 나뉜다.

  • Byte I/O : InputStream, OutputStream을 상속받아 생성되는 추상클래스이다.
  • Char I/O : Reader, Writer을 상속받아 생성되는 추상클래스이다.

이때 각 I/O 클래스의 핵심은, 생성자를 통해, 어디로 부터 Input을 입력받고 어디에 output을 출력할 것인지와 각 데이터의 type을 정의할 수 있다는 것이다.

1-1. 장식대상 클래스와 장식하는 클래스

  • 추상클래스 생성자를 통해 I/O data type을 정의할 수 있는지와 특정한 기능을 제공하는지
  • 이와 반대로 대상특정없이 다양한 방식으로 입출력하는 기능을 제공(및 추가)할 수 있는지

위 기준에 따라 장식대상 클래스 - 장식하는 클래스로 나눌 수 있다.

  • 장식대상 클래스
    각각 Input type이 file, array 등 특징되어있는 상태에서 입출력 메소드를 사용한다.
  • 장식하는 클래스
    I/O 대상을 특정하지 않는 상태에서 다양한 방안의 입출력 기능을 제공한다.

1-2. Decorator pattern

Java 입출력 패키지에서 제공하는 클래스들이 가지고 있는 pattern으로, decorator pattern으로 클래스가 구성되어 있다.

하나의 클래스를, 마치 장식하는 것과 같이 생성자에 추가함으로써 새로운 기능을 계속 추가할 수 있도록 클래스를 만드는 방식을 Decorator pattern이라 한다.

2. Byte 단위의 입출력

file을 byte 단위로 입력받고 저장한다.
클래스 이름이 InputStream, Outputstream으로 끝나는 특징을 가지고 있다.

import java.io.FileInputStream;

public class Byte{
	public static void main(String[] args){
    	FileInputStream fis = null;
    	
        fis = new FileInputStream("src/....");
    }
}

참고로 아래와 같이, file을 입력받는 경로를 설정해주면 된다.

이후 input한 file을 write할 수도 있는데, 이때는 output stream을 사용한다.
특히 유의해야할 점은 각 input stream, output stream은 예외객체를 생성하기 때문에 반드시 예외처리를 해주어야 문법적 오류가 발생하지 않는다.

import java.io.FileInputStream;

public class Byte{
	public static void main(String[] args){
    	FileInputStream fis = null;
 		FileOutputStream fos = null;
        
        try{
        fis = new FileInputStream("src/....");
        fos = new FIleOutputStream("fileouput.txt");
        
        int readData = -1; //file을 읽을 수 없다면 -1
        while(readData = fis.Read() != -1){
        	//fis의 file을 1byte씩 읽어들인다.
            fos.write(readData); //file write하여 file 생성
        }
    	} catch(FileNotFoundException e){
        	e.printStackTrace();
        }finally{
        	....
        }
    }
}

최종적으로 finally 구문에도 fis, fos 객체를 close하는 메소드를 추가적으로 작성해야하며, 이 역시 exception을 발생시키므로 try-catch 문을 활용한다.

finally{
	try{
    	fos.close();
    } catch(IOException e){
    	e.printStackTrace();
    } finally {
    	try{
        	fis.close();
        }catch(IOException e){
			e.printStackTrace();
        }
    }
}

위와 같이 지정해준 파일 경로에 해당 data(file)을 write한 file이 생성되었다.

3. Byte 단위 입출력 개선

위에서는 1byte씩 file data를 input - write하기 때문에 전체적인 수행시간 측면에서 매우 비효율적이고 느릴 수 밖에 없다.
input - write하는 data 크기를 512byte로 늘린다면 그만큼 시스템이 개선될 수 있는데, 이때 해당 file을 임시적으로 읽어들이는 buffer 배열을 사용한다.

int readData = -1;
byte[] buffer = byte[512]; //512byte 배열생성

write(readData = fis.read(buffer) != -1){
	fos.write(buffer, 0, readData);
}

4. file input size - 512byte 설정 원리

보통 file size가 512byte로 구성되어있기 때문에, 읽어들일때 사용하는 임시 공간인 buffer는 512byte 만큼 설정해주는 것이 좋다.

특히 1byte씩 읽는다면, 해당 data를 읽을때마다 512byte씩 만큼 읽고 읽은 1byte를 제외한 나머지 data를 폐기하는 과정을 순회하기 때문에 512byte buffer를 설정한다면 이러한 반복순회가 줄어들어 시스템 성능을 개선할 수 있다.

5. 참조자료

프로그래머스 강의 - I/O 패키지
https://programmers.co.kr/learn/courses/9/lessons/266

0개의 댓글