HANCO

[JAVA] BufferedReader / BufferedWriter 본문

Programming/JAVA

[JAVA] BufferedReader / BufferedWriter

HANCO 2020. 5. 3. 16:45

BufferedReader & BufferedWriter

자바에 기본입력을 받을 때 사용하는 Scanner (import java.util.Scanner)
편하게 값을 입력받을 수 있게 만들어지는 내장 라이브러리이다.

최근에 실무에서는 Scanner보다 BufferedRead와 BufferedWrite를 주로 사용한다는 소식을 들었다.
그렇게 때문에 Buffered 쌍둥이를 사용하는 방법을 공부해 볼 예정이다.

buffer을 사용하기 전에 왜 편리한 Scanner를 사용하지않고 buffer를 이용한 입출력을 사용하는지를 알고 있어야한다.

Scanner의 경우 다양한 타입으로 입력을 받을 수 있게 제공한다. 또한, 엔터, 공백등 을 스트링을 나누는 경계로서 인정하고 있기 때문에 다양한 방법으로 데이터를 받아와 처리할 수 있다.(유연하다고 해두자) 하지만 대량의 데이터를 입력받을 떄 (보통 실무에서는 소량데이터를 입력받기보다 수 많은 데이터의 이동이 이루어진다고 한다) Scanner는 같은 작업을 반복할 수 있기 때문에 비효율적인 입출력 처리를 한다.

이에 반하여 BufferedReader & BufferedWriter는 빠른 속도로 입력을 받을 수 있다. 결과부터 이야기 하고 시작하자면 Scanner로 100만개의 숫자를 입력받을 때의 속도는 약 2400ms BufferedRead는 450ms 100만개 입력값 기준 5배이상의 효율차이가 난다.

그렇다면 왜? 대체 왜?? 이런 차이가 발생하는 것일까? 몇가지 차이점에 대해서 알아보자

  1. 버퍼 크기의 차이

    Scanenr의 버퍼크기는 1024chars이고 BufferedReader의 버퍼크기는 8192chars이다. 버퍼크기가 8배 차이난다.
    그렇기 때문에 함번에 많은 양의 데이터를 버퍼에 저장하여 사용할 수 있다.

  2. 동작방식

    Scanner는 사용자가 데이터를 요청할 때마다 즉!, 반복문이 한번 돌때마다 계속해서 Scanner가 데이터를 읽어와 동작한다.
    그에 반해서 BufferedReader는 버퍼가 가득찰때까지 계속해서 데이터를 저장하고 있다가 버퍼가 다 찼다고 하면 스트링형태로 한번에 반환해준다.
    정리하자면 Scanner는 개행시 계속 해서 메서드가 호출되어 입력을 받고, bufferedReader는 버퍼가 찰때까지 버퍼에 데이터를 저장하고 있다가 다 찼을 때 데이터를 반환하기 때문에 속도의 차이가 발생한다.

이정도 속도의 차이라면 당연히 Bufferd 쌍둥이를 사용할 이유는 충분하다고 생각되어진다. 그렇다고 무작정 BufferedReader & BufferedWriter를 사용하는 사용자들은 사용법에 당황할 수 있다. 그 이유는 위에서 Scanner는 다양한 타입의 데이터를 받는데 좋다고 했지만 BufferedReader는 그렇지 않다. 오로지 String타입으로만 데이터를 받아올 수 있다. 그렇기 때문에 Integer이나 Double, boolean타입의 데이터를 입력값으로 받아와 사용하고 싶다면 데이터를 가공하는 작업이 필요하다. 아래에서 그 작업방법에 대해서 알아보자.

StringTokenizer

BufferedReader는 데이터를 String 덩어리형태로 받아오기 때문에 이 덩어리를 배열처럼 쪼개서 사용하는 가공작업이 필요하다.
그때 사용하는 것이 StringTokenizer이다. 자바에서는 기본으로 Stringtokenizer클래스를 제공하기 때문에 import후 쉽게 사용할 수 있다.

쉽게 말해서 String 형태의 데이터 "1 2 3 4 5 6 7 8 9"를 입력 받는다고 해보자 StringTokenizer를 사용하면 배열에 '1' '2' '3' '4' '5' '6' '7' '8' '9'형태로 일정 토큰을 통해 문자열을 잘라서 제공한다.(여기서 사용한 토큰은 공백이 될 것이다)

간단하게 사용방법을 알아보자.
우리는 1부터 100까지의 숫자를 받아와 사용해야한다고 해보자!

    // 처음보는 것이 있어서 당황할 수 있다.(InputStreamReader)
    // InputStreamReader를 사용함으로써 입력속도를 향상시킬 수 있다고만 알아두자 다른 포스팅에서 다룰 것이다.
    BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

    // StringTokenizer 객체사용
    StringTokenizer st = null;

    // 앞서 말했듯이 BufferedReader는 String형태로 데이터를 받는 것이 기본이기 때문에 Integer형으로 형변환하는 가공이 필요
    // 이부분이 데이터를 받는 곳이다.
    int num = Integer.parseInt(br.readLine());

    // 데이터를 저장하고 출력을 확인하기 위해 배열을 만들어보자
    // num의 크기보다 1큰 배열을 만들었다
    int [] arr = new int[num+1]

    // 토큰을 사용하기위해 코딩 (기본적으로 공란을 토큰으로)
    st = new StringTokenizer(br.readLine());

    // 반복문
    for(int i=1;i<=num;i++){
        arr[i] = Integer.parseInt(st.nextToken());
    }

    // 출력
    System.out.println(Arrays.toString(arr));

이로써 BufferedReader을 사용하는 이유와 방법에 대해서 간단한 포스팅을 마치겠다.
이번 포스팅에서는 BufferedWriterd을 다루지 않않다는 것을 눈치챈 사람들이 있을 것 같다.
사용은 다음시간에 다루도록 하겠다.ㅎㅎ 그럼이만!

'Programming > JAVA' 카테고리의 다른 글

[JAVA] 배열과 연결리스트  (0) 2020.11.05