Scanner보다 빠른 입력 BufferedReader, StringTokenizer

2022. 5. 3. 14:08Java/[도서] 자바의 정석

알고리즘 문제를 풀 때 입출력을 좀 더 빠르게 해야 할 경우가 생깁니다.

그중 오늘은 입력 클래스를 정리하려 합니다.

 

저는 원래 쓰기 간편한 Scanner를 주로 이용하였었는데요, 같은 문제를 풀었을 때, Scanner와 BufferedReader를 사용했을 때의 처리속도가 2배 이상 난 경우도 있었습니다.

 

이번 포스팅 정리를 통해서 BufferedReader, StringTokenizer를 이해하는 시간을 가져보도록 하겠습니다.

 

 

 

 

Scanner

// Scanner 사용 시 입력 형태.
Scanner sc = new Scanner(System.in);

int n = sc.nextInt(); 	   // int
String s1 = sc.next();     // String
String s2 = sc.nextLine(); // String

 

 

BufferedReader

BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); // 선언
String s = bf.readLine(); 		 //String
int i = Integer.parseInt(bf.readLine()); //Int

입력은 readLine(); 활용합니다. 

 

[[ 주의할 점 ]]
1. readLine() 시 리턴값은 String으로 고정되기에 String이 아닌 다른 타입으로 입력을 받기 위해서는
   형변환을 꼭 해주어야 합니다.

2. 예외처리를 꼭 해주어야 합니다.
    readLine을 할 때마다 try & catch를 활용하여 예외처리를 할 수도 있지만
    주로 throws IOException을 사용합니다.

 

 

데이터 가공

Read 한 데이터는 Line단위로만 나눠지기에 공백 단위로 데이터를 가공하려면 따로 작업을 해주어야 합니다.

대표적인 두 가지 방법을 소개합니다.
1. StringTokenizer에 nextToken() 함수를 쓰면 readLine()을 통해 입력받은 값을 공백 단위로 구분하여
   순서대로 호출할 수 있습니다.

2.String.split() 함수를 활용하여 배열에 공백 단위로 끊어서 데이터를 넣고 사용하는 방식입니다.

 

Case 1.

StringTokenizer st = new StringTokenizer(s); //StringTokenizer인자값에 입력 문자열 넣음
int a = Integer.parseInt(st.nextToken()); 
int b = Integer.parseInt(st.nextToken());

 

Case 2.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] s = br.readLine().split(" "); 
		
		System.out.print(Arrays.toString(s));
	}
}

입력과 출력 결과

입력 : 1 2 3 4 5 6 7 8 9 10 11 12
출력 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

 

StringTokenizer 사용 목적과 사용법

  • StringTokenizer는 공백이 있다면 뒤에 문자열이 공백 자리를 당겨 채웁니다.
  • 문자열을 자르게 위해 split을 사용할 시 split은 정규식을 기반으로 하기에 복잡합니다.
  • 그에 비해 StringTokenizer의 nextToken() 메서드는 단순히 공백 자리를 당겨 채우는 것이므로
    속도 차이가 발생합니다.
  • 정규식이나 인덱스 접근과 같은 처리가 필요 없다면 StringTokenizer를 사용하는 것이 효율적입니다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in);
StringTokenizer st = new StringTokenizer(br.readLine());

// AB CDD EFFF GH 입력

st.nextToken() // AB
st.nextToken() // CDD
st.nextToken() // EFFF
st.nextToken() // GH

 

String str = "my||name||is||Lea"; 
StringTokenizer st = new StringTokenizer(str,"||"); 

	while(st.hasMoreTokens()) { 
	        System.out.println(st.nextToken()); 
	    }

출력 결과

my
name
is
Lea

 

 


 

 

 

BufferedReader사용

BufferedReader br = new BufferedReader(new InputStreamReader(System.in);

br.readLine();

 

StringTokenizer사용

StringTokenizer st = new StringTokenizer(br.readLine(), " ");

 

 

활용 예제)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

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

		StringTokenizer st = new StringTokenizer(br.readLine(), " ");

		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());
		
		System.out.println(N);
		System.out.println(M);
	}

}

입력과 출력 결과

입력 : 123 456

출력 :
123
456

 

 

 

 

 

출처)

https://jeongkyun-it.tistory.com/entry/%EC%9E%85%EB%A0%A5-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%A0%95%EB%A6%AC-Scanner-BufferedReader-StringTokenizer

https://velog.io/@mooh2jj/Java-%EC%9E%85%EC%B6%9C%EB%A0%A5-BufferedReader-StringTokenizer%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0

https://coding-factory.tistory.com/251

https://hjjooace.tistory.com/entry/JAVA-%EC%9E%85%EC%B6%9C%EB%A0%A5-%ED%99%9C%EC%9A%A9BufferedReader-StringTokenizer