-
[JAVA] BufferedReader & Scanner & System.in카테고리 없음 2024. 1. 31. 01:15
JAVA에서는 키보드로부터 값을 받아오는 방법 2가지가 존재한다.
두 방법 사이에 어떤 차이가 있고, 어떤 구조를 가지는지 알아보려고 한다.
1. Scanner
Scanner는 키보드의 입력이 발생할 때마다 값이 바로바로 전달된다
장점
공백 및 개행 문자를 기준으로 읽어들이기 때문에 쉽게 데이터를 구분하여 받을 수 있다.
데이터 타입을 지정할 수 있기 때문에(nextInt( ), nextFloat( ) ,, ) 별도의 타입 캐스팅이 필요하지 않다.
단점
입력받을 때마다 전송이 되기 때문에 시간적인 측면에서는 비효율적이다.
Thread unsafe한 성질을 지니기 때문에 멀티스레드 환경에서는 문제가 될 수 있다.
2. BufferedReader
BufferedReader는 입력 받은 값을 기본적으로 8KB 크기의 버퍼에 담아두었다가 한번에 프로그램에 전송한다.
장점
매 입력마다 전송하는 것이 아니라, 한번에 전송하기 때문에 전송 처리에 드는 시간이 단축될 수 있다.
Thread Safe한 성질을 지니기 때문에 멀티스레드 환경에서도 안전하다.
단점
데이터 파싱 없이 String으로만 읽어오기 때문에(read.line( )만 가능) 별도의 데이터 처리 과정이 필요하다
반드시 예외 처리를 명시해야한다 (throws IOException)
Buffer ; 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 해당 데이터를 보관하는 임시 메모리 영역
2-1. InputStreamReader
InputStreamReader는 Character 단위(한 글자 단위)로 읽어 들인다.
(조금 더 구체적으로는 InputStream 을 통해 byte로 읽어온 문자를 InputStreamReader를 통해 char 로 연결지어준다)
짧은 데이터에서는 빠르게 값을 읽어올 수 있지만, 길이가 긴 문자열을 읽어야 할 때에는 값을 하나하나 읽어야하기 때문에 굉장히 비효율적이다.
따라서 BufferedReader를 함께 사용하며 InputStreamReader를 통해 읽은 Char들을 보관했다, 요청 시에 한번에 전달할 수 있기 때문에 긴 값이라도 빠르게 값을 전달할 수 있다.
( [byte] InputStream → [char] InputStreamReader → [String] BufferedReader )
3. System.in
Scanner 와 InputStreamReader 를 사용하기 위해선 둘 다 System.in 을 받는다.
- Scanner(System.in)
- InputStreamReader(System.in)
System.in 은 Java에서 기본으로 import 되는 표준입력스트림으로, 키보드에서 발생하는 입력 값을 받아와서 메모리의 주소로 저장된다.
따라서 해당 메모리 주소를 인자로 버퍼 저장된 값을 출력하는 클래스/메소드가 필요하다.
우선 Scanner 클래스를 보면 System.in 은 결국 InputStream 타입이라는 것을 볼 수 있다.
InputStream 으로 받은 System.in 은 InputStreamReader 로 넘겨져서 처리가 된다.
InputStreamReader 로 넘겨진 InputStream 은 InputStreamDecoder로 전달된다.
이 이상은 너무 깊어지니 일단 여기서 멈추고 정리를 해보자면
System.in 은 키보드로부터 입력을 byte로 받기 때문에
InputStream 타입으로 받아 InputStreamReader(char) 를 통해 문자로 변환되게 된다.
이렇게 변환된 문자를 buffer 에 저장해 String 으로 관리하는 것이 BufferedReader
변환된 문자를 원하는 타입으로 관리하는 것이 Scanner 이다.
Scanner vs BufferedReader
1. 사용성 : Scanner > BufferedReader
- BufferedReader는 String 형식으로만 읽어오기 때문에 별도의 처리 과정이 필요하지만,
- Scanner의 경우 원하는 타입으로 읽고, 공백 및 개행문자로 구분이 가능하다.
2. 메모리 : Scanner < BufferedReader
- BufferedReader의 버퍼 메모리는 8KB, Scanner의 버퍼 메모리는 1KB 이기 때문에,
BufferedReader가 더 큰 메모리를 점유하지만 1KB보다 큰 입력이 있을 경우에 더 효율적이다.
3. 안전 : Scanner < BufferedReader
- 동기화를 지원하는 BufferedReader는 싱글스레드인 Scanner보다 약간 느린데,
Scanner의 경우 정규식을 사용하여 입력을 받으므로 BufferedReader가 문자열을 더욱 빠르게 입력받을 수 있다.
4. 속도 : Scanner < BufferedReader
<결론>
보통 Scanner가 사용 측면에서 더 편리하긴 하지만, 속도는 BufferedReader가 더 우세하다
데이터의 길이가 짧거나, 구문 분석이 필요하다면 Scanner를
입력이 많고, 데이터를 한 줄로 받아와야 한다면 BufferedReader 를 사용하면 될 것 같다.특히 속도를 고려해야하는 코딩 테스트 문제에서는 BufferedReader를 사용해서 값을 받아오는 것인다는 개인적 견해다.
참고 자료
https://whitewing4139.tistory.com/219
https://velog.io/@langoustine/Scanner-VS-BufferedReader