[Java] 입력 InputStream, Scanner, BufferedReader 비교
본문 바로가기
Java

[Java] 입력 InputStream, Scanner, BufferedReader 비교

by IYK2h 2022. 7. 26.
728x90

InputStream

InputStream 의 정의는

This abstract class is the superclass of all classes representing an input stream of bytes.

이 추상 클래스는 바이트의 입력 스트림을 나타내는 모든 클래스의 슈퍼 클래스입니다.

여기서 중요한건 "바이트 입력 스트림"이다.

byte 란?

하나의 단위로서 다루는 비트(bit)의 모임. 8비트의 모임을 1바이트라고 한다.

Stream 이란?

Stream in java
A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.

스트림(Stream)은 원하는 결과를 생성하기 위해 파이프라인화될 수 있는 다양한 방법을 지원하는 객체의 연속이다.

Stream은 데이터의 이동 통로라고 해석할 수 있다.

즉, InputStream 데이터를 byte 단위로 입력하는 통로이고 , OutputStream은 출력 통로이다.

InputStream (System.in) / System.in은 무엇인가?
Scanner sc = new Scanner(System.in);

System Class의 in은 InputStream Type 이다. 즉, System.in 이 InputStream 타입의 필드이다.

*System 클래스 in 변수는 '표준 입력 스트림'이며 일반적으로 콘솔, 명령줄 인수 등을 통해 입력을 받다. 키보드, 터미널 등에서 입력을 넣어주는 것들을 System.in 을 통해 연결된다는 의미

테스트 해보자

import java.io.IOException;
import java.io.InputStream;

public class Main {

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

        InputStream inputstream = System.in;
        int a = inputstream.read();
        System.out.println(a);

    }
}

1을 입력하면

12를 입력하면

결과가 49로 같은 값이 나온다.

이유는 InputStream은 1바이트 단위로 입력받는다. 그래서 1의 아스키코드 값인 49, 12에서 첫 1바이트 값인 1의 아스키코드 값인 49가 나오게 된다.

import java.io.IOException;
import java.io.InputStream;

public class Main {

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

        InputStream inputstream = System.in;
        int a = inputstream.read();
        System.out.println(a);

        int b = inputstream.read();
        System.out.println(b);
    }
}

이렇게 b를 추가해 값을 읽어주면

1,2 각각의 아스키코드값이 나온다.

만약 n개의 문자를 입력받고 싶으면 n개의 변수를 선언해야하나 싶겠지만, 바이트 타입 배열로 선언해 read()메소드에 넣어서 입력받는 방법도 있다.

import java.io.IOException;
import java.io.InputStream;

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

        InputStream inputstream = System.in;

        byte[] a = new byte[2];
        inputstream.read(a);

        for(byte val : a){
            System.out.println(val);
        }
    }
}

결과는 위에 2개의 변수를 선언한 값과 같다.

 

Scanner

주로 아래와 같이 사용하는데

Scanner sc = new Scanner(System.in)

오버리이딩 된 Scanner 를 보면

InputStream을 통해 입력된다.

자세히 보면 Scanner() 생성자들이 this를 통해서 private Scanner(Readable source, Pattern pattern) 으로 넘겨진다.

여기서 InputStreamReader가 나온다.

InputStreamReader이란?

An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted.

InputStreamReader는 **"바이트 스트림에서 문자 스트림으로의 브리지" **입니다. 바이트를 읽고 지정된 문자 집합을 사용하여 바이트를 문자로 디코딩합니다. 사용하는 문자 집합은 이름으로 지정되거나 명시적으로 지정되거나 플랫폼의 기본 문자 집합이 허용될 수 있습니다.

전에 알아본 InputStream에서 1Byte씩 받은 문자를 문자단위인 character로 변환시키는 중개자 이다. 문자스트림이라고 불리기도 한다.

InputStream 은 Byte Type, 바이트 단위

InputStreamReader 은 char Type, 문자 단위

 

추가로, Scanner 가 느리다고 많이들 얘기하는데 느린 이유는 Scanner는 수많은 정규식을 통해 검사 된 문자열을 반환하기 때문에 느려진다. 정규식 자체도 느리지만 정규식의 양이 많다.

 

BufferedReader

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

위에서 정리한게 이해됐다면 BufferedReader 도 금방 이해가 가능할거라 생각된다.

BufferedReader를 선언할 때 new BufferedReader(new InputStreamReader(System.in)) 를 사용한다.

즉, BufferedReader는 문자를 받는다.

우리는 문자열을 입력할때 문자열의 길이가 가변적이다. 그래서 Buffer(버퍼)를 통해 입력받은 문자를 쌓아둔 뒤 한 번에 문자열처럼 보내버린다.

BufferedReader의 입력 메소드로 readLine()을 많이 쓴다. 이 메소드는 한 줄 전체(공백 포함)를 읽기 때문에 char 배열을 하나하나 생성할 필요 없이 String 으로 리턴하여 바로 받을 수 있다는 장점을 가지고 있다.

즉, 문자를 가변적으로 받아 문자의 직렬화를 통해 문자열을 만들게 된다.

정리하면,

System.in -> InputStream -> InputStreamReader -> BufferedReader

  입력      ->     Byte type    ->         char type            ->         String

또한 BufferedReader는 따로 정규식 검사를 진행하지 않고, 버퍼에 저장해 String을 만든다.

그래서 Scanner에 비해 성능이 좋다.

 

가볍게 정리해보면

Scanner 에서 InputStreamReader 를 사용하는 이유는 문자를 온전하게 받기 위함이고

Scanner의 메소드 next(), nextInt() 등은 타입에 맞게 정규식을 검사해서 상대적으로 느리다

 

Reference

https://www.geeksforgeeks.org/stream-in-java/#:~:text=A%20stream%20is%20a%20sequence,Arrays%20or%20I%2FO%20channels.

728x90

댓글