본문 바로가기

알고리즘(Java)

[JAVA] 알고리즘 풀 때 유의해야 할 차이(Scanner, BufferedReader)

알고리즘 문제를 풀 때 자주 쓰는 클래스들이다. 기본적인 거지만, 약간의 유의할 점이 있어서 스크랩하게 되었다.

===========================================================

 

첫번째 : Scanner와 BufferedReader의 차이

 

Scanner


J2SE 5.0 (Java 1.5) 에 Scanner 라는 java.util.Scanner 클래스가 새로 추가되었다. Scanner 클래스를 이용하면 콘솔입력을 보다 쉽게 처리 할 수 있다.

package test;

import java.util.Scanner;

public class Test {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

int integerNum = sc.nextInt();
long longNum = sc.nextLong();
double doubleNum = sc.nextDouble();
String str = sc.next();
String strWithSpace = sc.nextLine();
// 등등...
sc.close();

System.out.println(integerNum);
System.out.println(longNum);
System.out.println(doubleNum);
System.out.println(str);
System.out.println(strWithSpace);
}
}




  BufferedReader


 
package test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Test {

public static void main(String[] args) {

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

OutputStreamWriter osw = new OutputStreamWriter(System.out);
BufferedWriter bw = new BufferedWriter(osw);

try {

// 입력
String line = br.readLine();

// 출력
bw.write(line);
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

InputStreamReader는 입력을 character로 읽어들인다. 키보드로 입력하는 글자 한개에 해당된다고 할 수 있다. 하지만 한 글자가 아닌 줄단위의 문자열을 입력으로 받으려면 마찬가지로 불편하다. 그래서 생겨난 것이 BufferedReader이다.


BufferedReader는 InputStreamReader에 버퍼링 기능을 추가한 것으로 데이터를 사용자가 요청할때마다 매번 읽어오기 보다는 일정량사이즈로 한번에 읽어온 후 버퍼에 보관한다. 그리고 사용자가 요구할 때 버퍼에서 읽어오게 한다. 결국 BufferedReader를 이용하면 속도를 향상시키고 시간의 부하를 줄일수 있게 된다.


BufferedReader는 사용하기 위해 import도 BufferedReader와 InputStreamReader 2개를 불러와야 하지만 Scanner는 Scanner 하나만 불러오면 된다는 차이도 있다.


BufferedReader는 throws Exception을 선언해 주어야지만 에러 없이 사용 가능 하기 때문에 실질적으로 Scanner보다 손도 훨씬 많이 가고, 장점이 별로 없다 할 수 있다.




  하지만,, 속도


출처 : algospot


Scanner의 버퍼 사이즈는 1024 chars 이고, BufferedReader의 버퍼사이즈는 8192 chars이기 때문에 많은 입력이 있다면 BufferedReader가 성능 상 우위를 가질 수 밖에 없다. Scanner는 내부적으로 regex를 매우 많이 이용하기 때문인 것으로 보입니다.



출처: http://cocomo.tistory.com/507 [Cocomo Coding]

 

 

 

두번째 : Scanner클래스의 next(), nextLine()의 차이와 특징

 


next() 메서드는 하나의 단어만 입력을 받고,
nextLine() 메서드는 한줄을 입력 받는다.


예제를 통한 특성 분석

Scanner s = new Scanner("\n\n\n가나다\n\n라\n\n");

로 입력을 받는경우

예1)
while(s.hasNext()){
str = s.next();
System.out.println("출력:"+str);
}

결과1)
출력:가나다
출력:라

※ next() 메서드는 첫 단어 앞쪽 공백이나 개행문자는 무시하고 하나의 단어를 입력받고, 단어 뒤의 개행문자는 그대로 나둔다.

예2)
while(s.hasNext()){
str = s.nextLine();
System.out.println("출력:"+str);
}

결과2)
출력:
출력:
출력:
출력:가나다
출력:
출력:라

※ nextLine() 메서드는 개행문자(\n)까지를 한줄로 인식하고 입력을 받고 \n는 버려진다.

※ hasNext() 메서드는 남은 버퍼에 개행문자만 남은경우 false를 반환하지만, 개행문자는 그대로 남아있다.


예3)
Scanner s = new Scanner("우리나라\n대한민국\n");


str = s.next();
System.out.println("출력:"+str);
str = s.nextLine();
System.out.println("출력:"+str);


str = s.nextLine();
System.out.println("출력:"+str);
결과3)
출력:우리나라
출력:
출력:대한민국

※ next() 메서드 실행뒤에 첫단어만 가져오고 개행문자가 앞에 남기때문에 다음 nextLine()을 만나면 개행문자를 한줄로 가져오게 된다.

※ next()뿐만 아니라 nextInt()등과 같은 메서드와 nextLine()메서드를 섞어 사용할 경우에는 주의해야 한다.


예4)
Scanner s = new Scanner("10008\n홍길동 입니다.");
int i = s.nextInt();
System.out.println("코드:"+i);
String str = s.nextLine();
System.out.println("이름:"+str);

출력4)
코드:10008
이름:

※ 위 예는 맞는거 같지만 예3 에서와 같이 nextInt()와 nextLine()을 섞어 사용했을때 범하기 쉬운 오류부분입니다.


위 상황에서의 해결방법은 두가지가 있습니다.

개선1)
Scanner s = new Scanner("10008\n홍길동 입니다.");
int i = s.nextInt();
System.out.println("코드:"+i);
s.nextLine(); //개행문자 제거를 위함
String str = s.nextLine();
System.out.println("이름:"+str);

개선2)
Scanner s = new Scanner("10008\n홍길동 입니다.");
int i = Integer.parseInt(s.nextLine()); //라인으로 입력받아 int타입으로 변환
System.out.println("코드:"+i);
String str = s.nextLine();
System.out.println("이름:"+str);

개선결과)
코드:10008
이름:홍길동 입니다.

※ 보통 키보드를 통한 입력은 한줄 단위 입력을 많이 하기 때문에 nextLine()으로 입력받아 필요한 타입으로 변환하여 입력하는 방법도 좋을듯 합니다.

 

출처 : http://sexy.pe.kr/tc/496