새벽코딩

[JAVA] 입력 (Scanner vs BufferedReader) 본문

JAVA

[JAVA] 입력 (Scanner vs BufferedReader)

J 코딩 2022. 11. 13. 15:45
반응형

자바에서는 크게 두가지 방법으로 IO Input을 받을 수 있다.
1. Scanner
2. BufferedReader
 
[Scanner]
 
먼저, Scanner객체는 java.util.Scanner에 포함되어있어서 이를 사용하기 위해서는
해당 패키지를 import해야한다.
 
Scanner를 단순한 입출력에 이용하는데에는 아무런 문제가 없지만 이를 이용해 알고리즘 문제를 풀때에는 해당 객체의 버퍼사이즈정도를 알고 있는 것이 좋다.
Scanner객체는 버퍼사이즈가 1024byte이며, 입력 받을 시 내부적으로 정규화 식을 가동하기 때문에 대량 데이터를 입력 받을 때에는 많은 시간이 소요된다.
 

import java.util.Scanner

Scanner sc = new Scanner(System.in);

/* 숫자 변수 입력 */

// int 자료형 변수 입력
int i = sc.nextInt();

// short 자료형 변수 입력
short j = sc.nextShort();

// long 자료형 변수 입력
long k = sc.nextLong();

// double 자료형 변수 입력
double h = sc.nextDouble();

// float 자료형 변수 입력
float f = sc.nextFloat();

/* 문자열 자료형 변수 입력 */

// 공백문자까지 입력
String str1 = sc.next();

// 줄단위로 입력
String str2 = sc.nextLine();

/* boolean 자료형 변수 입력 */
boolean b = sc.nextBoolean();

 
Scanner는 사용자의 입력을 받기 위해 가장 흔하게 사용하는 객체이므로 그 종류들을 알고 있는게 좋다.
 
[BufferedReader]
 
두번째는, BufferedReader클래스이다.
이 클래스를 사용하기 위해서는 java.io.IOException을 import해야한다.
 
BufferedReader의 버퍼크기는 8192byte로 Scanner보다 8배 크며, 이 클래스는 입력된 문자를 중간에 버퍼에 담고 있다가 버퍼가 가득차면 출력하는 방식이다.  그렇기 때문에 실시간으로 개별 출력하는 출력방식보다 속도가 빠르다.
 

import java.io.IOException;

public static void main(String[] args) throws IOException {

    BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
    String str = buf.readLine();
    
    // BufferedReader로 받은 데이터 가공
    StringTokenizer st = new StringTokenizer(str);
    
    // nextToken을 이용해서 공백별로 데이터를 나눌 수 있다.
    String str1 = st.nextToken();
    String str2 = st.nextToken();
    String str3 = st.nextToken();
}

 
BufferedReader클래스는 입력되는 문자열을 개행별로 인식하기 때문에 개행이 아닌 공백이나 다른 문자열 별로 나누려면 따로 가공해줄 필요가 있다. 
예로 "This is Test"라는 문자열을 공백별로 나눠서 담고 싶을 때는 위의 StringTokenizer을 사용하여 값을 나눠담을 수 있다.
 
버퍼크기의 차이 때문에 각 입력에는 동작원리의 차이가 있다.
 
Scanner는 버퍼의 크기(1024byte)가 작기 때문에 입력되는 동시에 출력이 이루어지며, 작업중 내부에서 예외처리(try~catch), 정규표현식 적용, 데이터 파싱등의 여러 과정을 거친다.
BufferedReader클래스는 내부에서 따로 예외처리를 해주지 않기 때문에 올바른 입력값이 들어왔는지 처리해주도록 IOExcetption으로 예외처리를 해주어야한다.
 
 
글을 작성하다보니 백준알고리즘 문제를 풀때 자주 사용했던 StringBuilder라는 녀석이 궁금해졌다.
 
StringBuilder는 일반 String이 가지고 있는 메모리 부족문제를 해결하기 위한 대안으로 사용 될 수 있다.
String객체는 연산동안에 기존의 메모리를 바로 갱신하거나 버리지 않고 가비지(Garbage)에 보관하고 있다가 메모리 사용이 과다하다고 생각되거나 오랫동안 사용되지 않다고 판단될때 GarbageCollection에 의해 제거된다.
 
이에 반해, Stringbuilder는 가변성을 가지는 객체로서 데이터가 연산을 통해 변한다고 하더라도 메모리사용에 크게 영향을 주지 않는다. 여기서 가변성을 갖는다는 개념에 간단히 설명하고 넘어가자면
 

String str = "TEST DATA";
str.append("입니다.")

StringBuilder sb = new StringBuilder();
sb.append("TEST DATA");
sb.append("입니다.");

 
위의 str은 append하여 문자열을 합칠 때 해당 메모리의 주소가 바뀌게 된다. 이는 처음에 초기화한 str과 두번째 append한 str이 서로 다른 주소를 가진다라는 개념을 가진다.
여기서 불변한다는 것은 첫번째 str이 처음 가진 메모리주소는 바뀌지 않는 다는 것 때문에 불변한다고 이야기 하는 것이다.
 
sb는 메모리의 주소값이 바뀌지 않는다 값이 가변해도 주소의 값은 바뀌지 않기 때문에 메모리의 사용을 최소화 할 수 있다. 값이 바뀌면 해당 메모리의 주소도 바뀐변수를 따라오게 된다. 이른 가변성을 가진다고 말한다.
 
이렇게 Scanner와 BufferedReader의 차이에 대해 정리해 보았다.
결론은 대량의 입력이 존재하는 프로그램일경우 Scanner보다는 BufferedReader가 용이하며 소량의 입렵일 경우에는 큰 차이가 없으므로 Scanner를 사용하는 것이 간단할 수 있겠다.
 
또한 문자열의 연산이 많이 일어날 수 있는 알고리즘 같은 경우에는 String을 사용해서 메모리를 낭비하는 것보단 StringBuilder를 사용하여 메모리 사용을 최소화 하도록 해보자.

반응형

'JAVA' 카테고리의 다른 글

[JAVA] 배열과 리스트  (0) 2023.02.26
[JAVA] 오버로딩(feat. this)  (0) 2023.02.25
[JAVA] try~catch  (0) 2023.02.23
Comments