이제는 BufferedReader을 마음대로 쓰지만, 처음에는 이것도 오우.. 이게 뭐야..? 하면서 거리 두고 Scanner만 주구장창 썼다. 그러다가 백준에서 15552. 빠른 A+B 문제를 만나게 됐는데 여기서 시간 초과나면서 기절할 뻔., 그 이후에 BufferedReader 깔짝거리다가 이제는 정착해버리게 되었다. 어차피 정리할 거라면 BufferedReader 나왔을 때 정리하는 게 맞는 것 같아서 지금 정리랑 공부함 ( 사실 지금 정리하면서 알게 됨)
먼저 Scanner부터 정리해보자.
The Scanner class is used to get user input, and it is found in the java.util package.
To use the Scanner class, create an object of the class and use any of the available methods found in the Scanner class documentation.
https://www.w3schools.com/java/java_user_input.asp
다시 말해서, Scanner는 java.util.package에 있는 user가 입력받는 데 사용되는 클래스이다.
import java.util.Scanner;
Scanner sc = new Scanner(System.in);
여기서 System.in은 콘솔 입력을 받음.
💡System.in
자바에서 표준 입력스트림(Standard InputStream)을 나타내는 객체로 키보드 입력과 같은 사용자 입력을 처리하기 위해 사용됨
- 사용자가 입력한 데이터를 바이트 단위로 읽음
- 자바의 InputStream 클래스 타입으로 byte stream을 처리함
- System.in 자체로는 byte 수준의 입력만 처리하므로 보통 Scanner나 BufferedReader 같은 고수준 입력 클래스를 통해 더 쉽게 활용
- 문자열 입력 : nextLine()
- 정수 입력 : nextInt(), nextLong()
- 실수 입력 : nextFloat(), nextDouble() 등
💡nextInt() vs nextLong()
nextInt() nextLong() 입력 데이터 타입 int long 범위 -2,147,483,648 ~ 2,147,483,647 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 사용 목적 작은 정수 값을 처리할 때 큰 정수 값을 처리할 때
이런 식으로 Scanner에 대해 알 수 있었다.
그럼 왜 Scanner만 쓰면 되지 왜 BufferedReader을 써서 머리를 복잡하게 할까?
BufferedReaer에 대해 논할려면 Buffer부터 말하는 게 좋을 것 같다.
In computer science, a data buffer (or just buffer) is a region of a memory used to temporarily store data while it is being moved from one place to another
https://en.wikipedia.org/wiki/Data_buffer
어떤 데이터가 다른 장소로 전달될 때, 임시로 저장되는 메모리 영역이라고 여기서는 말한다.


위 그림에서 보듯이 한 곳에서 다른 곳으로의 데이터 흐름을 스트림이라고 한다.
그리고 스트림은 단방향이기 때문에 입력과 출력이 동시에 발생할 수 없다. 그렇기 때문에 용도에 따라 입력스트림, 출력스트림이 나뉜다.
여기서 스트림은 파일을 읽거나 쓸 때, 데이터가 전송되는 통로라고 생각하면 좋을 것 같다.
즉, Stream은 데이터가 전송되는 통로
자바에서 데이터를 효율적으로 읽어들이기 위해 사용하는 클래스. 주로 텍스트 데이터를 처리할 때 사용되며, 기본적으로 입력 스트림(Input Stream) 또는 Reader를 감싸서 데이터를 버퍼(buffer)에 저장한 뒤 한 번에 처리한다.
BufferedReader in = new BufferedReader(new InputStreamReader (System.in));
키보드와 같은 사용자로부터 입력을 받는 표준입력스트림 객체를 나타낸다. 그래서, System.in의 리턴값은 InputStream이다.
※ InputStream : 입력스트림으로부터 데이터를 byte단위로 읽어오는 byte stream이다.
BufferedReader는 보조스트림으로써 Char 데이터를 반환한다는 것을 알 수 있다.
하지만 BufferedReader는 말그대로 보조스트림이기 때문에, 직접적으로 데이터를 Char 형태로 받지 못하고, 이전의 데이터가 Char 형태로 넘어와야 버퍼링을 적용하여 반환해줄 수 있다.
이 때 사용되는 것이 바로 InputStreamReader이다. InputStream -> Reader로 변환해주는 역할로 Byte 형태를 Char 형태로 변환해준다.
BufferedReader는 인자로 취한 Reader 스트림에 버퍼링기능을 추가한 입력스트림 클래스입니다. 버퍼를 둠으로써 파일,네트워크와 같은 물리적인 장치에서 데이터를 사용자가 요청할 때마다 매번 읽어오는것보단 일정량사이즈로 한 번에 읽어온 후 버퍼에 보관합니다. 그리고, 사용자가 요구시 버퍼에서 읽어오게됩니다. 결국, 속도를 향상시키고, 시간의 부하를 줄일수 있게 됩니다.

Scanner가 느린 이유는, 입력을 읽는 과정에서 정규 표현식을 적용하고, 입력값 분할, 파싱 과정을 스스로 제공해주기 때문이다.
실제로, Scanner에서 제공하는 .nextInt(), .nextDouble() 메서드는 잘못 입력하면 입력 단계에서부터 예외가 발생한다.
BufferedReader는 모든 입력을 Char형으로, 버퍼를 사용하여 받는다.
하나의 글자에 대해 전달이 이루어지는 것이 아닌, 전체 입력(혹은 버퍼 단위)에 대해서만 전달되기 때문에 속도 부분에서 매우 유리할 수 밖에 없다.
그래서 속도는 빠르지만, 사용자가 사용하기 편하게 조작하려면 별도의 메서드를 호출해야한다.
출처
https://velog.io/@roycewon/BufferedReader%EB%A5%BC-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90
https://st-lab.tistory.com/41
https://itmaster98.tistory.com/31
https://crazykim2.tistory.com/535
https://wickedmagic.tistory.com/50
https://velog.io/@kkimbj18/%EB%B2%84%ED%8D%BC%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-Feat.-BufferedReader-vs-Scanner-cache