뭐라도 끄적이는 BLOG

Java I/O 본문

Java/Java 기본

Java I/O

Drawhale 2023. 7. 2. 10:47

I/O 입출력

입출력(I/O)이란 Input과 Output의 약자로 입력과 출력을 말한다. 흔히 줄여서 입출력이라고들 많이 말하며 컴퓨터 내부 또는 외부 장치와 프로그램간의 데이터를 주고 받는 것을 말한다. 예를들어 파일이나 네트워크에서 데이터를 읽고 파일에 쓰거나 네트워크를 통해 응답을 하는 동작 모두 입출력이라고 한다.

Java.io & java.nio

java에는 java.io와 java.nio 2가지 IO 패키지가 존재한다. nio는 new-io라고도 하며 Non-Blocking io라고도 한다.

IO NIO
Stream Buffer
단방향 양방향
Blocking IO Non blocking IO
Selectors

java.io

스트림 (Stream)

Java에서 어느 한 쪽에서 다른 쪽으로 데이터를 전달하려면 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요하다. 이것을 스트림(Stream)이라고 정의 한다. 즉, 스트림은 데이터를 운반하는데 사용되는 연결 통로이다. 물이 한방향으로 흐르는 것과 같이 스트림은 단방향통신만 가능하다. 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다. 입력과 출력을 동시에 처리하기 위해 입력을 위한 입력 스트림(input stream)과 출력을 위한 출력(output stream) 2가지의 스트림이 필요하다.

스트림은 먼저 보낸 데이터를 먼저 받게 되어 있으며 중간에 건너 뜀없이 연속적으로 데이터를 주고 받는 FIFO(First In First Out) 구조로 되어 있다.

Byte스트림과 Character 스트림

Stream은 2가지 종류로 나눠볼 수 있다. 입출력 되는 데이터를 단순 1바이트의 스트림으로 처리하는 바이트 스트림, 2byte의 문자를 입출력 하기 위한 문자 스트림 이다.

바이트 스트림은 이미지, 동영상 등을 송수신 할 때 주로 사용되며 문자 스트림은 일반적인 텍스트 데이터나 JSON, HTML등을 송수신할 때 사용된다.

InputStream OutputStream 계층도
Reader Writer 계층도

InputStream & OutputStream

스트림은 Byte단위로 데이터를 전송하며 입출력 대상에 따라서 다음과 같은 입출력 스트림이 있다.

입력스트림 출력 스트림 입출력 대상
FileInputStream
FileOutputStream
파일
ByteArrayInputStream ByteArrayOutputStream 메모리(byte배열)
PipedInputStream PipedOutputStream 프로세스(프로세스간 통신)
AudioInputStream AudioOutputStream 오디오 장치

어떠한 대상 또는 입력을 할것인지 출력을 할 것인지에 따라 해당 스트림을 선택해서 사용할 수 있다. 위 입출력 스트림은 각각 InputStream과 OutputStream의 자손들이며, 각각 읽고 쓰는데 필요한 추상 메서드를 자신에 맞게 구현해 놓은 구현체들이다.

InputStream

Java I/O input stream의 기본 클래스 

  • abstract int read()
  • int read(byte[] b)
  • int read(byte[] b, int off, int len)

입력의 대상에 따라 읽는 방법이 다를 것이기 때문에 상황에 맞게 구현하라는 의미로 추상 메소드로 정의되어 있다. 나머지 메소드들도 read()를 이용해서 구현한것이므로 read()가 구현되어 있지 않으면 아무런 의미가 없다.

OutputStream

Java I/O output stream의 기본 클래스

  • abstract void write(int b)
  • void write(byte[] b)
  • void write(byte[] b, int off, int len)

마찬가지로 출력의 대상에 따라 방법이 다를것이기때문에 추상메서드로 정의 되어 있다. write(int b)를 구현하여야 나머지 메소드들도 의미가 있으므로 구현해야 한다.

보조 스트림

스트림의 기능을 보완하기 위한 것이다. 보조스트림은 실제 데이터를 주고 받지 않고 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있다. 다른 스트림을 감싸고 있다는 뜻에서 Wrapper 스트림이라고도 한다.

입력스트림 출력 스트림 목적
BufferedInputStream BufferedOutputStream 입출력 성능 향성을 위한 버퍼
DataInputStream DataOutputStream 데이터를 자료형을 선택

※참고: 데코레이터 패턴

java.io 패키지는 데코레이터 패턴으로 만들어졌다. 데코레이터 패턴이란 주어진 상황 및 용도에 따라 객체에 책임을 추가하는 패턴이다. 

버퍼 (Buffer)

byte, char, int등 기본 데이터 타입을 저장할 수 있는 저장소로서, 배열과 마찬가지로 제한된 크기에 순서대로 데이터를 저장한다.

버퍼는 데이터를 저장하기 위한 것이지만, 실제로 버퍼가 사용되는 것은 채널을 통해서 데이터를 주고 받을 때 쓰인다. 채널을 통해서 소켓, 파일 등에 데이터를 전송할 때나 읽어올 때 버퍼를 사용하게 됨으로 써 가비지량을 최소화 시킬 수 있게 되며, 이는 가비지 콜렉션 회수를 줄임으로써 서버의 전체 처리량을 증가시켜준다.

java.nio

New IO라는 뜻으로 java4에서 추가된 패키지 입니다. 채널 (Channel) 기반의 I/O 이다.

채널

데이터가 통과하는 쌍방향 통로이며, 채널에서 데이터를 주고 받을 때 버퍼가 사용된다.

buffer , non-buffer

버퍼를 사용하면 입출력 데이터를 버퍼에 모아놓고 한꺼번에 보내는 일이 가능하다. 한꺼번에 보낼 수 있다면 IO횟수가 줄어들어 전체 시간을 함께 줄일 수 있다.

NIO는 기본적으로 버퍼를 사용한다. 버퍼내에서 데이터의 위치를 이동해 가면서 필요한 부분만 읽고 쓸 수 있다.

IO는 기본적으로 버퍼를 사용하지 않는다. 때문에 읽은 데이터를 즉시 처리하게 된다. 그래서 입력된 데이터의 위치를 이동하거나 하는 작업은 불가능하다. 이러한 단점을 보조스트림을 이용하여 극복하고 있다.

표준 스트림 (System.in, System.out, System.err)

Method Description
System.in 키보드로 입력된 값을 읽는다. 더이상 읽을수 없으면 -1을 반환한다.
System.out 콘솔로 출력을 하는 표준 스트림을 가리키는 상수
System.err 표준 에러 출력 장치를 가리키는 상수. err는 정확하고 빠르게 출력되어야 되기 때문에 버퍼링을 지원하지 않는다.

파일 읽고 쓰기

파일 읽기

public class FileInputOutputEx {
    public static void main(String[] args){
        Resource resource = new ClassPathResource("text.txt");
        try(BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))){
            String line;
            while ((line = reader.readLine())!= null){
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

파일 쓰기

public class FileInputOutputEx {
    public static void main(String[] args){
        ClassPathResource resource = new ClassPathResource("write.txt");
        try(BufferedWriter writer = new BufferedWriter(new FileWriter(resource.getPath()))){
            writer.write("Hello");
            writer.newLine();
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

이진파일의 경우 각각 InputStream과 OutputStream으로 변경하면 된다.

반응형

'Java > Java 기본' 카테고리의 다른 글

Java Lambda  (0) 2023.07.02
Java Generic  (0) 2023.07.02
Java Annotation  (0) 2023.07.02
Java Enum  (0) 2023.07.02
Java Thread  (0) 2023.07.02