Background
Java로 입력값을 받아야 하는 입력값을 받아야 하는 알고리즘 문제를 풀 때 Scanner를 사용했는데
BufferedReader가 더 좋다는 소리를 듣고 어떤 특징이나 차이가 있는지 찾아봤다.
Scanner
Scanner 클래스는 입력받은 데이터(바이트)를 다양한 타입으로 변환하여 반환하는 클래스이다.
간단하게 기본형과 String 타입을 정규표현식을 사용해 파싱할 수 있다.
Scanner 특징
- java.util 패키지에 속한다. (java.util.Scanner)
- 공백(띄어쓰기) 및 개행(줄 바꿈)을 기준으로 읽는다. (' ', '\t', '\r', '\n' 등)
- 원하는 타입으로 읽을 수 있다.
- 버퍼의 크기가 1024 byte(1KB) 이다.
- UnChecked(Runtime) Exception으로 별도의 예외 처리를 명시할 필요가 없다.
- Thread unsafe 성질을 지니기에 멀티스레드 환경에서 문제가 발생할 수 있다.
- 데이터를 입력받을 경우 즉시 사용자에게 전송되며 입력받을 때마다 전송되어야 하기에 많은 시간이 소요된다.
Scanner 작성 예
import java.util.Scanner;
...
Scanner sc = new Scanner(System.in);
String st = sc.nextLine();
System.in 이란 사용자로부터 입력을 받기 위한 입력 스트림이다.
Scanner 클래스뿐 아니라 다른 입력 클래스들도 System.in을 통해 사용자 입력을 받아야 한다.
BufferedReader
데이터를 한 번에 읽어와 버퍼에 보관한 후 버퍼에서 데이터를 읽어오는 방식으로 동작하는 클래스이다.
즉, 사용자가 입력한 문자 스트림을 읽는 것이다.
버퍼(buffer)란 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 해당 데이터를 보관하는 임시 메모리 영역이다.
주로 입출력 속도 향상을 위해 버퍼를 사용한다.
(Java에서는 BufferedReader와 BufferedWriter라는 클래스를 제공하여 다룰 수 있다.)
BufferedReader 특징
- java.io 패키지에 속한다. (java.io.BufferedReader)
- 데이터를 파싱하지 않고 String으로만 읽고 가져온다.
- 버퍼의 크기가 8192 byte(8KB)이다.
- Checked Exception으로 반드시 예외 처리를 명시해야 한다. (I/O Exception을 throw하거나 try/catch 해야한다.)
- Thread safe 성질을 지니기에 멀티스레드 환경에서도 안전하다.
- 버퍼가 가득차거나 개행문자가 나타나면 버퍼의 내용을 한 번에 프로그램으로 전달하기에 Scanner보다 소요되는 시간을 절약할 수 있다.
BufferedReader 작성 예
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
...
public static void main(String[] args) throws IOException {
BufferReader br = new BufferedReader(InputStreamReader(System.in));
String st = br.readLine();
int a = Integer.parseInt(br.readLine());
int b = Integer.parseInt(st);
}
InputStreamReader란 문자 기반의 보조 스트림으로써 바이트 기반 스트림을 문자 기반 스트림으로 연결시켜 주는 역할을 한다.
Scanner vs BufferedReader
- Scanner는 BufferedReader보다 타입에 구애받지 않는다.
- BufferedReader는 String 형식으로만 읽고 저장하기에 형변환을 위한 추가적인 코드 작성이 불가피한 반면에 Scanner는 원하는 타입으로 읽고 파싱할 수 있다.
- Scanner의 경우 int, long, short, float, double의 경우 nextInt(), nextLong(), nextShort(), nextFloat(), nextDouble()과 같은 함수들을 사용할 수 있다.
- BufferedReader는 readLine() 함수만을 사용한다.
- BufferedReader는 Scanner보다 안전하다.
- Scanner는 Thread-unsafe 하기에 멀티스레드 환경에서 안전하지 않지만, BufferedReader는 안전하다.
- 스레드 간 Thread-unsafe 하기에 멀티스레드 환경에서 안전하지 않지만, BufferedReader는 안전하다.
- BufferedReader가 Scanner보다 실행 속도가 빠르다.
- 백준에서의 입력속도를 보면 BufferedReader는 0.68585초, Scanner는 4.8448초가 평균적으로 소요된다.
- BufferedReader는 Scanner보다 효율적인 메모리 용량을 가진다.
- Scanner는 1KB 크기의 버퍼를 갖기 대문에 입력이 바로 전달되는 반면,
BufferedReader는 8KB 크기의 버퍼를 가져 buffer에 입력들을 저장했다가 한 번에 전송하기 때문에 속도가 더 빠르다. - Scanner는 입력을 읽는 과정에서 내부에서 정규 표현식 적용, 입력값 분할, 파싱 과정 등을 거치기 때문에 속도가 느리다.
- Scanner는 1KB 크기의 버퍼를 갖기 대문에 입력이 바로 전달되는 반면,
References
https://velog.io/@langoustine/Scanner-VS-BufferedReader
https://dlee0129.tistory.com/238