자바스터디 - 13주차

megaseunghan·2022년 8월 19일
0

자바스터디

목록 보기
13/15
post-thumbnail

목표

자바의 Input과 Ontput에 대해 학습하세요.

학습할 것 (필수)

  • 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
  • InputStream과 OutputStream
  • Byte와 Character 스트림
  • 표준 스트림 (System.in, System.out, System.err)
  • 파일 읽고 쓰기

스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O

java.iojava.nio

각 기반의 I/O를 살펴보기에 앞서 자바에서의 I/O는 java.io, java.nio의 두 패키지로 나눠진다. 나는 이 둘을 큰 틀로 잡고 비교하여 정리하였다.

java.iojava.nio의 차이점

io, nio는 입출력, 버퍼, 비동기, 블로킹/넌블로킹의 방식이 서로 다르다.

구분IONIO
입출력 방식스트림 방식채널 방식
버퍼 방식넌버퍼(non-buffer)버퍼(buffer)
비동기 방식지원 안 함지원
블로킹 / 넌블로킹 방식블로킹 방식만 지원블로킹 / 넌블로킹 방식 모두 지원

위 표를 보고 각 방식의 차이점에 대해 알아보자

스트림 vs 채널

  • IO는
    • 스트림 기반이다. 스트림은 입력 스트림과 출력 스트림이 따로 구분되어 있으며 예를 들어 파일을 읽고 쓴다면 각자의 스트림(입, 출력)이 필요하다. 스트림은 FIFO(First In First Out)구조이다.
  • NIO는
    • 채널기반이며 채널은 양방향이다. 파일을 읽고 쓴다면 하나의 채널로 입, 출력이 가능하다.

버퍼 vs 넌버퍼

  • IO는

    • 출력 스트림이 1바이트를 쓰면 입력 스트림이 1바이트를 읽는다.(넌버퍼는 느리다)
    • 보조 스트림(BufferedInputStream, BufferedOutputStream)을 연결하여 사용하기도 한다.
    • 스트림에서 읽은 데이터를 즉시 처리한다. 그렇기 때문에 스트림에서 입력된 전체 데이터를 별도로 지정하지 않으면 데이터의 위치 이동이 자유롭지 않다.
  • NIO는

    • 버퍼를 사용해서 입출력을 한다(IO보다 성능이 좋다). 채널은 버퍼에 저장된 데이터를 출력하고 입력된 데이터를 버퍼에 저장한다.
    • 읽은 데이터를 무조건 버퍼에 저장하기 때문에 버퍼 내에서 데이터의 위치를 이동해가면서 필요한 부분만 읽고 쓸 수 있다.
  • 버퍼란

    • 데이터를 전송하는 상호간의 장치에서 고속의 장치와 저속의 장치간의 속도 차이로 인한 저속 장치를 고속 장치가 기다려주는 현상을 줄여주는 기술이다. 데이터를 임시로 저장한다.
  • 버퍼를 쓰면 빨라지는 이유

    • OS레벨의 콜 시스템 횟수가 줄어들기 때문에 빨라지는 것이다.

블로킹 vs 넌블로킹

  • IO는
    • 블로킹이 가능하다.
    • read()를 호출하면 입력되기 전까지 Thread가 블로킹 된다. 반대로 write()를 호출해도 마찬가지로 Thread가 블로킹 된다. 빠져 나오는 유일한 방법은 스트림을 닫는 것이다.
  • NIO는
    • 블로킹, 넌블로킹 특징을 모두 가진다.
    • NIO 블로킹은 인터럽트를 사용해서 빠져나올 수 있다.
    • NIO 넌블로킹은 데이터가 바로 읽고 쓸 수 있는 상태의 채널만 선택해서 작업 스레드가 처리하기 때문에 블로킹되지 않는다(Selector를 연결한다).

IO는 왜 느릴까?

자바에서 I/O를 처리하는 영역은 유저영역 / 커널영역으로 구분할 수있다.

  • 유저영역 - 실행 중인 프로세스 제어 가능
  • 커널영역 - 하드웨어까지 제어 가능

InputStream과 OutputStream

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

InputStream

inputStream

출처 코딩팩토리 : https://coding-factory.tistory.com/281

InputStream은 바이트 기반 입력 스트림의 최상위 추상클래스이다. 읽기에 대한 다양한 추상 메서드가 있으며 목적에 따라 데이터를 입력 받을 수 있다.

OutputStream

outputStream

​ 출처 코딩 팩토리 : https://coding-factory.tistory.com/281

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

Byte와 Character 스트림

바이트 기반 스트림 - InputStream, OutputStream

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

바이트기반은 입출력의 단위가 1byte라는 것이다.

입력 스트림출력 스트림입출력 대상의 종류
FileInputStreamFileOutputStream파일
ByteArrayInputStreamByteArrayOutputStream메모리(byte배열)
PipedInputStreamPipedOutputStream프로세스(프로세스간의 통신)
AudioInputStreamAudioOutputStream오디오장치

위와 같이 여러 종류의 입출력 스트림이 있으며 필요에 따라 원하는 스트림을 사용하면 된다.

문자 기반 스트림 - Reader, Writer

앞서 바이트 기반 스트림은 1byte를 입출력의 단위로 사용한다고 하였다. 하지만 자바에서 한 문자는 2byte를 차지하기 때문에 바이트 기반 스트림으로 문자를 처리하는데에는 어려움이 있다. 이 점을 보완하기 위해 문자기반의 스트림이 제공된다.

  • InputStream -> Reader
  • OutputStream -> Writer

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

자바에서는 표준 입출력을 위해 3가지의 입출력 스트림을 제공한다. 이 스트림들은 자바 애플리케이션의 실행과 동시에 사용할 수 있게 자동적으로 생성되기 때문에 개발자가 별도로 스트림을 생성하는 코드를 작성하지 않고도 사용이 가능하다.

아래 3가지는 모두 System 클래스에 속해 있는 클래스(static) 변수이다. 선언부분에는 InputStream, PrintStream이라고 적혀있지만 실제로는 BufferedInputStream, BufferedOutputStream의 인스턴스를 사용한다.

public final class System {
    public static final InputStream in;
    public static final PrintStream out;
    public static final PrintStream err;
    ...
}
  • System.in - 콘솔로부터 데이터를 입력받는데 사용
  • System.out - 콘솔로 데이터를 출력하는데 사용
  • System.err - 콘솔로 데이터를 출력하는데 사용

파일 읽고 쓰기

자바에서는 io패키지의 File 클래스를 통해서 파일과 디렉토리를 다룰 수 있도록 하고 있다. 더불어 nio 패키지에서는 좀 더 다양한 파일의 속성 정보를 제공해주는 클래스와 인터페이스를 java.nio.file, java.nio.attribute패키지에서 제공한다.

IO패키지 File 클래스 특징

  • File 클래스는 파일크기, 속성, 이름 등의 정보를 얻어내는 기능, 파일 생성, 삭제의 기능을 제공한다.

  • 그러나 파일의 데이터를 읽고 쓰는 기능은 지원하지 않는다.

  • 파일의 입출력은 Stream을 사용한다.

0개의 댓글