자바는 입력 메서드가 두 가지인데, 바로 BufferedReader와 Scanner이다.
처음 자바를 시작 할 때는 Scanner를 쓰다가, 나중에 속도가 중요해질 때가 생기면 보통 BufferedReader를 사용한다.
그럼 이 두 입력 클래스의 차이는 뭘까? 왜 속도에 차이가 나는걸까?
1. Buffer
버퍼는 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 해당 데이터를 보관하는 임시 메모리 영역이다. 쉽게말해 '데이터 임시 저장공간'이라고 할 수 있다.
위의 그림처럼, 버퍼를 사용하지 않는 입력은 키보드의 입력이 발생하는 순간 바로바로 프로그램으로 전달된다(입력값 인식 경계와 별개). 하지만 버퍼를 사용하게 되면 키보드의 입력을 바로 보내는 것이 아니라 버퍼에 순서대로 적재하고, 입력이 개행문자이거나 버퍼가 가득 차면 쌓아놓았던 문자를 한 번에 프로그램으로 전달한다.
이때, 물건을 하나하나 옮기는 것 보다 박스에 여러 개를 담아 한 번에 옮기는 것이 더 빠른 것처럼, 키보드의 입력마다 전달하는 것보다 한 번에 전달하는 것이 속도가 빠르다.
여기서 버퍼를 사용하지 않는 입력은 Scanner이고, 버퍼를 사용하는 입력은 BufferedReader 이다(이때 BufferedReader의 버퍼 크기는 8KB이다). 따라서 버퍼를 사용하는 BufferedReader가 Scanner 보다 속도가 빠르다.
2. 문자열 파싱
Scanner와 BufferedReader는 입력단위와 타입도 다르다.
Scanner는 띄어쓰기와 개행문자를 경계로 입력 값을 인식한다. 더불어 숫자형을 입력받는 메서드가 따로 있는 등 다양한 입력메서드가 존재해 입력값을 따로 가공할 필요가 없다.
예를 들어 Scanner로 int형 변수를 입력받으려면 nextInt()를 사용하면 바로 int형 숫자를 하나 가져올 수 있다. 또한 단어 하나를 입력받으려면 next()를, 한 줄 전체를 입력받으려면 nextLine()을 사용하면 된다.
하지만 BufferedReader는 개행문자를 경계로 입력값을 인식한다. 즉 한 줄씩만 입력받을 수 있다! 따라서 데이터가 String으로 고정되어 다른 타입의 데이터라면 사용을 위해 가공할 필요가 있다.
예를 들어 한 줄에 여러 단어가 입력되었을 때 하나만 얻고 싶다면 readLine()으로 한 줄을 전부 읽은 다음 StringTokenizer나 split()을 사용해 단어별로 분리 해 사용해야 한다.
3. 예외
입출력 예외가 발생했을 때 두 클래스의 대응도 다르다.
Scanner의 메서드들은 입출력 에러가 발생할 경우 IOException을 숨기도록 정의되어 있다. 따라서 메서드를 사용할 때 예외처리가 필수가 아니다.
하지만 BufferedReader의 메서드들은 입출력에러가 발생할 경우 자체적으로 IOException을 던지도록 정의되어 있다. 그러므로 이 메서드들을 사용할 때 반드시 예외처리를 해주어야 한다. (try-catch 혹은 throws IOException)
사용자 입력 클래스의 다른 점을 알아보았다. BufferedReader의 사용법은 함께 사용하는 BufferedWriter와 하께 따로 정리하도록 하겠다.