[Java] 입출력 I/O

이혜지·2022년 8월 7일
0

Java

목록 보기
3/3

스트림(stream)

어느 한쪽에서 다른쪽으로 데이터를 전달하하려면, 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요한데 이것을 스트림(stream)이라고 한다. (람다, 스트림에 나오는 스트림과 다른것)

스트림이란 데이터를 운반하는데 사용되는 연결통로이다.

입력과 출력을 동시에 수행하려면 입력을 위한 입력스트림과 출력을 위한 출력스트림. 모두 2개의 스트림이 필요하다.

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


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

예를들어 어떤 파일의 내용을 읽고자 하는 경우 FileInputStream을 사용하면 된다.

이들은 모두 InputStream또는 OutputStream의 자손들이며, 각각 읽고 쓰는데 필요한 추상메서드를 자신에 맞게 구현해 놓았다.

자바에서는 java.io 패키지를 통해서 많은 종류의 입출력관련 클래스들을 제공하고 있으며, 입출력을 처리할 수 있는 표준화된 방법을 제공함으로써 입출력의 대산이 달라져도 동일한 방법으로 입출력이 가능하기 때문에 프로그래밍을 하기에 편하다.

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)

read()의 반환타입이 byte가 아니라 int인 이유는 read()의 반환값의 범위가 0~255와 -1이기 때문이다

  • InputStream의 read()와 OutputStream의 write(int b)는 입출력의 대상에 따라 읽고 쓰는 방법이 다를 것이기 때문에 각 상황에 알맞게 구현하라는 의미에서 추상메서드로 정의되어있다.
  • read()와 write(int b)를 구현하지 않아도 이들을 사용하면 될 것이라고 생각할 수도 있겠지만, 사실 추상메서드인 read()와 write(int b)가 구현되어 있지 않으면 이들을 아무런 의미가 없다.
public abstract class InputStream {
	...
    //입력스트림으로 부터 1byte를 읽어서 반환한다. 읽을 수 없으면 -1을 반환한다.
    abstract int read();
    
    //입력스트림으로 부터 len개의 byte를 읽어서 byte배열 b의 off위치부터 저장한다.
    int read(byte[] b, int off, int len) {
    	...
        for (int i = off; i < off + len; i++) {
        	//read()를 호출해서 데이터를 읽어서 배열을 채운다.
            b[i] = (byte)read();
       
        }
        ...
        //입력스트림으로부터 byte배열 b크기만큼 데이터를 읽어서 배열 b에 저장한다.
        int read(byte[] b) {
        	return read(b, 0, b.length);
        }
    	...
    }


}

결론적으로 read()는 반드시 구현되어야하는 핵심적인 메서드이고, read()없이는 read(byte[] b, int off, int len)와 read(byte[] b)는 의미가 없다는 것을 확인할 수 있다.

보조 스트림


위에서 언급한 스트림 외에도 스트림의 기능을 보완하기 위한 보조스트림이 제공된다.

  • 보조스트림은 실제 데이터를 주고받는 스트림이 아니기 때문에 데이터를 입출력할 수 있는 기능이 없다.
  • 하지만 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있다.
  • 그래서 보조스트림만으로는 입출력을 처리할 수 없고, 스트림을 먼저 생성한 다음에 이를 이용해서 보조스트림을 생성해야한다.

예시

//먼저 기반스트림을 생성한다.
FileInputStream fis = new FileInputStream("text.txt");

//기반스트림을 이용해서 보조스트림을 생성한다.
BufferedInputStream bis = new BufferedInputStream(fis);

bis.read(); //보조스트림인 BufferedInputStream으로부터 데이터를 읽는다.

보조 스트림의 종류

입력출력설명
FileInputStreamFileOutputStream필터를 이용한 입출력처리
BufferedInputStreamBufferedOutputStream버퍼를 이용한 입출력 성능향상
DataInputStreamDataOutputStreamint, float와 같은 기본형 단위(primitive type)로 데이터를 처리하는 기능
SequenceInputStream없음두 개의 스트림을 하나로 연결
LineNumberInputStream없음읽어 온 데이터의 라인 번호를 카운트(1.1부터 LineNumberReaderfh eocp)
ObjectInputStreamObjectOutputStream데이터를 객체단위로 읽고 쓰는데 사용. 주로 데이터 파일을 이용하여 객체 직렬화와 관련있음
없음PrintStream버퍼를 이용하여, 추가적인 print관련 기능(print, printf, println메서드)
PushbackInputStream없음버퍼를 이용해서 읽어 온 데이터를 다시 되돌리는 기능(unread, push back to buffer)

문자기반 스트림 - Reader, Writer


위에 내용은 모두 바이트기반의 스트림이었다.
바이트기반이라 함은 입출력의 단위가 1byte라는 뜻이다.
Java에서는 한 문자를 의미하는 char형이 1byte가 아니라 2byte였기 때문에 바이트기반의 스트림으로 2byte인 문자를 처리하는 데는 어려움이 있다.
이 점을 보완하기 위해서 문자기반의 스트림이 제공된다. 문자데이터를 입출력할 때는 바이트기반 스트림 대신 문자기반 스트림을 사용하자.
InputStream -> Reader
OutputStream -> Writer

바이트기반 스트림과 문자기반 스트림의 비교

바이트기반 스트림문자기반 스트림
FileInputStreamFileReader
FileOutputStreamFileWriter
ByteArrayInputStreamCharArrayReader
ByteArrayOutputStreamCharArrayWriter
PipedInputStreamPipedReader
PipedOutputStreamPipedWriter
StringBufferInputStream(deprecated)StringReader
StringBufferOutputStream(deprecated)StringWriter
  • 참고: StringBufferInputStream, StringBufferOutputStream은 StringReader와 StringWriter로 대체되어 더이상 사용안함

바이트기반 보조스트림과 문자기반 보조스트림

바이트기반 보조스트림문자기반 보조스트림
BufferedInputStreamBufferedReader
BufferedOutputStreamBufferedWriter
FilterInputStreamFilterReader
FilterOutputStreamFilterWriter
LineNumberInputStreamLineNumberReader
PrintStreamPrintWriter
PushbackInputStreamPushbackReaer
profile
공유 문화를 지향하는 개발자입니다.

0개의 댓글