CORE
HOME > JAVA > J2SE > CORE
2019.05.29 / 24:51

[입출력] Scanner와 BufferedReader의 차이

탁돌이개발자
추천 수 23

먼저 이번 글은 Scanner BufferedReader에 대해 너무 깊은 부분까지는 들어가지 않고 단지 알고리즘 온라인 저지 사이트에서 입력시 속도 측면에서 얼마나 많이 차이가 나는지에 대해 알아보고자 쓰는 글이다.

우선 우리는 일반적으로 자바에서 입력을 받으려면 java.util 패키지에 있는 Scanner 클래스를 import해온다. 이렇게 단순히 import를 하고 Scanner sc = new Scanner(System.in); 처럼 써주는것 만으로도 간단히 스캐너를 사용할 수 있다.
그러나 스캐너의 경우 사용하기 편리하지만 속도가 느리다는 치명적인 단점이 있다.
간단한 예제를 통해 스캐너의 속도를 테스트해보자.

아래의 코드는 Scanner를 통해 1~100만, 즉 100만개의 데이터를 입력받는 코드이다.

import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); int t; sc.nextLine(); long st1 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ t = sc.nextInt(); } System.out.println("소요시간 "+(System.currentTimeMillis() - st1)+"ms"); sc.close(); } }

숫자 100만개를 입력받는데 걸리는 시간은 다음과 같다.

대충 2.5초 (2441ms)가 소요되었다. 100만개 입력에 2.5초라고 놓고 보면 빠른것 같지만 알고리즘 사이트의 경우 최대 입력받는 데이터가 천만~1억에 이르는 경우도 종종 있고, 무엇보다 다른 연산시간까지 고려하면 좀 결코 뛰어난 성능이라고 할 수는 없다.



이제 BufferedReader를 이용해 입력을 받아보자. 버퍼리더는 한줄을 통째로 입력받는 방법으로 이것저것 선언해야할 것이 많아 번거롭지만 비교적 빠를 수 있다는 장점이 있다.
대략적인 사용 설명을 하자면 이렇다.

import java.io.BufferedReader; import java.io.InputStreamReader; //이 2개 import필수(java.io.*; 로 전부 받을수도 있다.) public class Main { public static void main(String []args) throws Exception { //예외처리 필수 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String s = br.readLine(); //입력받을값이 String일때 int a = br.read(); //입력받을값이 int일때 int b = Integer.parseInt(br.readLine()); //int값+엔터 까지 입력받을때 } }

이런식으로 입력받을 수 있는데 알고리즘 사이트에서 데이터들은 대부분
1
2
3
이런식으로 한줄씩 띄워진 상태로 입력이 들어온다. 
따라서 int b를 입력받은 방법처럼 일단 스트링으로 개행문자(엔터)까지 포함해 통째로 받아온다음 형변환을 통해 저장한다.
또한 new BufferedReader(new InputStreamReader(System.in), 1024)); 이렇게 버퍼 사이즈를 직접 지정할 수도 있는데 아무것도 지정하지 않을시 디폴트 사이즈 버퍼를 갖는다. 어지간한건 디폴트 사이즈로도 충분했다.

아무튼 버퍼리더를 이용해 100만개의 값을 입력받는 코드와 결과는 아래와 같다.

import java.io.InputStreamReader; import java.io.BufferedReader; public class Main{ public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); in.readLine(); int t; long st2 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ t = Integer.parseInt(in.readLine()); } System.out.println("소요시간 "+(System.currentTimeMillis() - st2)+"ms"); } }

소요시간은 스캐너의 1/6수준인 약 0.4초(452ms)밖에 걸리지 않았다. 사실 위에서 얘기했다시피 버퍼리더는 한줄을 통째로 받는 방식이기 때문에
1 2 3 4 5 6 7 8 9 10 11 ... 
과 같이 한줄로 입력이 들어올때 스캐너에 비해 훨씬 성능이 더 높아진다.

따라서 문제 제출시 알고리즘상에 문제가 없는데도 불구하고 시간초과가 난다면 Scanner에서 BufferedReader로 바꿔 제출해보도록 하자.

물론 스캐너와 버퍼리더가 처음부터 동일한 목적으로 만들어진건 아니지만 채점상 시간을 줄일 수 있는 방법이므로 적절히 활용하면 큰 효과를 볼 수 있을 것이다.