프로그래밍 언어/자바(JAVA)

자바(JAVA) - Scanner & BufferedReader

나아가는중 2022. 1. 23. 19:02
반응형

자바(JAVA) - Scanner & BufferedReader


자바를 처음 배울 때 사용자(키보드) 입력받기 위해 보통 Scanner 클래스를 사용합니다. 하지만 알고리즘을 풀기 시작하면서 백준에서 Scanner를 사용하여 입력을 받으면 시간초과가 발생하는 경험을 하게 됩니다. 그래서 다른 방법을 찾다 보면 BufferedReader를 접하게 됩니다.

 

Scanner와 BufferedReader 클래스는 둘 다 사용자(키보드) 입력을 받을 수 있는 기능을 제공합니다. 두 클래스가 가지고 있는 함수들에도 많은 차이가 있지만 가장 큰 차이는 속도입니다.

 

Scanner와 BufferedReader의 사용법

import java.util.Scanner;

public class Input {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String input = sc.nextLine();
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Input {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String input = br.readLine();
    }
}

 

백준님이 작성하신 입력 속도 비교 글을 보면 평균적으로 BufferedReader 사용시에 0.6585, Scanner 사용시에 4.8448 초가 걸리는 차이가 있습니다. 적은 양의 데이터인 경우 문제가 없겠지만, 데이터 양이 많아질수록 성능 차이는 큽니다.

https://www.acmicpc.net/blog/search/%EC%9E%85%EB%A0%A5+%EC%86%8D%EB%8F%84 

 

블로그 - 전체 글

여러가지 언어와 입력 방법을 이용해서 시간이 얼마나 걸리는지 비교해 보았습니다. 방법: 첫째 줄에 정수의 개수 N (= 10,000,000), 둘째 줄부터 N개의 줄에 한 개의 자연수(10,000 이하)가 적힌 파일

www.acmicpc.net

 

BufferedReader를 사용할때와 Scanner의 속도가 차이가 나는 이유는 buffer 사용 여부의 차이입니다.

Scanner는 1KB 크기의 버퍼를 갖기 때문에 입력이 바로 전달되는 반면 BufferedReader는 8KB 크기의 버퍼를 가져 buffer에 입력들을 저장하였다 한 번에 전송하기 때문에 속도가 더 빠릅니다.

또한, Scanner는 입력을 읽는 과정에서 내부에서 정규 표현식 적용, 입력값 분할, 파싱 과정 등을 거치기 때문에 속도가 느립니다.

 

 

 

두 클래스가 공통적으로 생성할때에 System.in을 매개변수로 받는 것을 볼 수 있습니다.

System.in은 java.lang 패키지의 System 클래스이며, System클래스의 in은 정적(static) 변수입니다.

public final class System {
    public static final InputStream in = null;
    
    ...
}

inInputStream 타입의 변수임을 볼 수 있습니다.

InputStream은 java.io 패키지의 바이트 단위 입력을 위한 최상위 입력 스트림 클래스입니다.

 

System.in을 매개변수로 사용하기 때문에 사용자(키보드) 입력을 받을 수 있다고 생각하시면 됩니다.

다음과 같이 System.in만을 사용하여 입력을 받는 것이 가능합니다.

import java.io.IOException;

public class Input {
    public static void main(String[] args) throws IOException {
        int input = System.in.read();
    }
}

 

System.in과 BufferedReader 클래스를 사용할 때는 main 옆에 throws IOException이 붙습니다.

사용자의 입력은 여러 다양한 타입으로 들어올 수 있는데, 잘못된 값이 들어올 경우 에러가 나지 않도록 예외처리를 해줘야합니다.

 

Scanner는 System.in을 생성시에 내부에서 try-catch를 사용하여 예외처리를 하기때문에 예외처리를 하지 않아도 됩니다.

 

위의 코드를 보면 Scanner와 달리 BufferedReader는 생성시에 매개변수로 InputStreamReader를 사용합니다.

Scanner 또한 클래스 생성자에서 InputStreamReader를 생성하여 사용합니다.

public final class System {
    public Scanner(InputStream source) {
        this(new InputStreamReader(source), WHITESPACE_PATTERN);
    }    
    ...
}

따라서 다음과 같이 InputStreamReader를 생성하여 매개변수로 전달하는것도 가능합니다.

import java.io.InputStreamReader;
import java.util.Scanner;

public class Input {
    public static void main(String[] args) {
        Scanner sc = new Scanner(new InputStreamReader(System.in));
        
        String input = sc.nextLine();
    }
}

 

InputStreamReader란 문자 입력 스트림의 한 종류로 입력 장치(키보드 등)으로 부터 받은 입력 값을 자바 응용 프로그램으로 전달하는 객체입니다. 자바 응용 프로그램은 입력 장치로부터 직접 데이터를 읽지 않고 입력 스트림을 통해 데이터를 읽습니다.

 

스트림에 대해 자세히 알고 싶으시면 아래 포스트를 참조해주세요.

https://dlee0129.tistory.com/216?category=981263 

 

자바(JAVA) - 입출력 스트림

자바(JAVA) - 입출력 스트림 입출력 스트림이란? 스트림(Stream)을 한글로 번역하면 개울, 시내, 줄기, 줄줄 흐르다로 번역됩니다. 입출력 스트림에서 스트림은 순서가 있는 데이터의 연속적인 흐

dlee0129.tistory.com

 

반응형