[Java] 자바에서의 입출력과 문자기반 보조 스트림의 사용

kai6666·2022년 6월 12일
0

TIL. Java

목록 보기
19/21

💁‍♀️ 자바에서의 입출력 - 스트림(stream)

입출력은 컴퓨터 내/외부의 장치와 프로그램간의 데이터를 주고 받는 것이다. 자바에서는 데이터를 주고 받기 위해 즉 입출력을 위해 스트림이라는 것을 쓴다. 이것은 람다와 스트림에서의 스트림과 이름이 같지만 다른 개념이다.

스트림은 연속적인 데이터의 흐름을 물에 비유해서 붙여진 이름이다. 흐르는 물은 하나의 방향으로만 흐른다. 이 점은 스트림의 단방향통신이라는 특성과 유사하다. 스트림은 입출력을 동시에 수행할 수 없다. 때문에 입력스트림(input stream)출력스트림(output stream), 총 2개의 스트림이 필요하다.

스트림은 먼저 보낸 데이터를 먼저 받는다. 또한 중간에 건너뜀 없이 연속적으로 데이터를 주고 받는다. 이 특성은 큐(Queue)의 FIFO(First In First Out) 구조와 비슷하다.

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

자바의 스트림은 바이트단위로 데이터를 전송한다. 어떤 스트림을 쓸지는 어떤 대상에 대해 작업할 것인지에 따르기 때문에 위의 입력스트림과 출력스트림의 종류 중 적합한 것을 적용하면 된다. 이들은 모두 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)

자바에서는 java.io 패키지에 입출력 관련 클래스들을 제공하고 있다. 위의 메서드들은 InputStream과 OutputStream에 정의된 읽기와 쓰기 수행 메서드들이다. read()와 write(int b) 메서드를 제외한 나머지는 일반 메서드라서 이것만 써도 되는 것은 아니다. 이 메서드들은 추상메서드인 read()와 write(int b)를 통해 구현된 것이기 때문에 이 메서드들이 우선적으로 구현되어 있지 않으면 소용이 없다.


💁‍♀️ 보조 스트림

보조 스트림이란 앞서 살펴본 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있는 스트림이다. 보완하는 용도이기 때문에 실제 데이터를 주고 받지 않고, 데이터를 입출력할 수 있는 기능은 없다. 따라서 스트림을 먼저 생성한 후에 보조 스트림을 생성해서 써야 한다.

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

FileInputStream은 InputSream의 자손이고, BufferedInputStream, DataInputStream, LineNumberInputStream, PushbackInputStream은 모두 FileInputStream의 자손이기 때문에 입출력방법이 같다. 버퍼를 사용한 입출력은 사용하지 않았을 때보다 확연히 성능이 좋기 때문에 대부분의 경우에 버퍼를 이용한 보조스트림을 사용하는 것이 좋다.


💁‍♀️ 문자 기반 스트림 - Reader Writer

위의 스트림은 모두 바이트 기반 스트림이었다. 바이트 기반이라 함은, 입출력 단위가 1 byte라는 의미이다. 하지만 Java에서는 char형이 2 byte기 때문에 바이트 기반의 스트림으로 문자를 처리할 때 어려움이 있다. 이를 보완하기 위해 있는 것이 문자 기반 스트림이다.

바이트기반 스트림문자기반 스트림
FileInputStream, FileOutputStreamFileReader, FileWriter
ByteArrayInputStream, ByteArrayOutputStreamCharArrayReader, CharArrayWriter
PipedInputStream, PipedOutputStreamPipedReader, PipedWriter
StringBufferInputStream, StringBufferOutputStreamStringReader, StringWriter

문자기반 스트림은 바이트기반 스트림에서 InputStream/OutputStream 부분을 Reader/Writer로 바꾸면 된다. 마지막의 스트링버퍼I/O는 StringReader와 StringWriter로 완전히 대체되어 더 이상 사용되지 않는다.


💁‍♀️ 문자기반의 보조스트림

👉 BufferedReader와 BufferedWriter

BufferedReader와 BufferedWriter는 버퍼를 이용해 입출력의 효율을 높여준다. BufferedReader의 readLine()을 사용하면 데이터를 라인 단위로 읽을 수 있다. BufferedWriter의 newLine()을 사용하면 줄바꿈을 할 수 있다.

👉 InputStreamReader와 OutputStreamWriter

InputStreamReader와 OutputStreamWriter는 바이트 기반 스트림을 문자 기반 스트림으로 연결시켜준다. 바이트 기반 스트림의 데이터를 지정된 인코딩 문자 데이터로 변환하는 작업도 수행한다.

예를 들어 중국어로 작성된 파일을 읽을 때는 InputStreamReader로 인코딩이 중국어로 되어 있다는 것을 지정해주어야 파일이 깨지지 않고, 마찬가지로 파일에 텍스트 데이터를 저장할 때 OutputStreamWriter로 인코딩을 지정하지 않으면 OS가 자체적으로 사용하는 인코딩으로 데이터를 저장할 것이다.

✨ 백준 #15552번 풀이를 통해 살펴보는 문자기반 보조스트림의 사용

import java.io.*;

public class ABSum {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int num = Integer.parseInt(br.readLine());

        while(num > 0) {

            String line = br.readLine();
            int pos = line.indexOf(" ");
            int A = Integer.parseInt(line.substring(0, pos));
            int B = Integer.parseInt(line.substring(pos+1));
            int sum = A+B;

            bw.write(Integer.toString(sum));
            bw.newLine();

            num--;
        }
            bw.close();
    }
}
// 입력 :
//3
//1 2
//2 3
//4 5
// 출력 :
//3
//5
//9

BufferedReader와 BufferedWriter를 이용해 백준 15552번 문제를 푼 코드이다. BufferedReader로 첫째줄에 입력 받은 숫자가 0이 되기 전까지 입력 받은 숫자를 줄마다 반복해서 숫자로 뜯어낸 후, 그것을 더한 값을 BufferedWriter를 통해 줄마다 출력하게끔 작성하였다.


참고 자료

profile
성장 아카이브

0개의 댓글