Scanner와 BufferdReader의 차이
BufferedReader, BufferedWriter은 버퍼를 사용하여 읽기, 쓰기를 하는 함수이다.
버퍼를 사용하지 않는 입력은 키보드의 키를 누르는 즉시 프로그램에 전달된다.
버퍼를 사용하는 입력은 키보드의 입력 이 있을 때마다 한 문자씩 버퍼로 전송한다.
이 버퍼가 가득차거나 줄 바꿈을 하면 버퍼의 내용을 한 번에 프로그램에 전달한다.
Scanner은 1KB의 버퍼를 갖고, BufferedReader는 8KB의 버퍼를 가진다.
즉, Scanner은 더 자주 프로그램에 전달하고, BufferedReader은 조금 더 모아놨다가 프로그램에 전달한다.
( 쓰레기가 생길때마다 나가서 버리는 거랑, 쓰레기통에 모아놨다가 한 번에 버리는 차이 )
버퍼는 키보드와 프로그램 사이에 데이터 저장 공간 이라고 보면 될 것 같다.
또한, Scanner는 입력 시 내부에서 정규표현식, 입력값 분할, 파싱 과정 등을 상당히 많이 거치고 출력되기 때문에 속도가 느리다.
1. Scanner
1) 선언
Scanner sc = new Scanner(System.in);
2) 메서드
Scanner sc = new Scanner(System.in);
String str = sc.nextLine(); // 한줄 모두 입력받음
int i = sc.nextInt(); // 공백을 기준으로 하나의 int값을을 입력받음
3) 사용 예제
- 값을 받을 때,
Scanner
는 공백을 기준으로 값을 구분한다.
(입력)
1 2
3
(code)
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
System.out.println(a+b+c);
//a:1 , b:2 , c:3
// 6 출력
2. BufferedReader
1) 선언
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
2) 사용 방법
BufferedReader
는 입력을 한줄씩 읽어 들인다.
readLine()
메서드를 통해 한 줄을 입력받을 수 있다.
입력받음과 동시에 다음줄로 넘어가서, 다시 한번 readLine()
를 실행하면 그다음줄을 읽게 된다.
3) 예제 1
(입력)
abcd
efgh
(code)
String str1 = br.readLine();
String str2 = br.readLine();
(결과)
str1에는 "abcd"가, str2에는 "efgh"가 들어간다.
4) 예제 2
- BufferedReader는 한 줄을 전부 입력받기 때문에
StringTokenizer
와 함께 사용한다. StringTokenizer
를 사용하면 한 줄의 문자열에 담긴 내용을 어떤 기준(대부분 공백" "
)으로 나눌 수 있다.
(입력)
hi !! 456
hello world !!
(code)
StringTokenizer st = new StringTokenizer(br.readLine);
String str = br.readLine();
String str1 = st.nextToken();
String str2 = st.nextToken();
int value = Integer.parseInt(st.nextToken());
(결과)
str : "hello world!!"
str1 : "hi"
str2 : "!!"
value : 456
5) 예제 3
조금 더 복잡한 예제이다.
첫째 줄에서 세로 N = 3 , 가로 M = 4 , 값 V = 99를 입력받고
2~4째 줄에서 int[N][M] board에 값을 입력받는 과정을 알아보자.
우선 첫째줄을 br.readLine으로 읽어와서 st에 넣어준다.
그렇게 되면 st에 3, 4, 99가 문자열 형태로 담기게 된다.
각각 st.nextToken()으로 N, M, V에 값을 할당해 준다.
그 아래부터는 한줄에 한 행씩 값이 들어온다.
따라서 한 주기가 끝날 때 마다 st = new StringTokenizer(br.readLine()); 으로 갱신해 준다.
안쪽 for문에서는 바깥쪽 for문 에서 새롭게 선언한 st를 이용해서 st.nextToken()으로 값을 가져오는 것을 반복한다.
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()); //가로
int V = Integer.parseInt(st.nextToken());
int[][] ground = new int[N][M];
for(int i=0;i<N;i++){
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
ground[i][j] = Integer.parseInt(st.nextToken());
}
}
3. BufferedWriter
1) 선언
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
2) 사용 방법
write()
메서드를 이용하여 BufferedWriter에 입력받는다.flush()
메소드를 이용해서 console에 직접 출력한다.
- 한번
flush()
로 출력하고, 다시write()
를 이용해 입력받고 다시 출력할 수 있다.
3) 단점
BufferedWriter는 비동기적 버퍼 스트림이다.
즉, 입력받은 데이터가 점점 채워지다가 버퍼가 꽉 차버리면 버퍼에 있는 데이터를 자동으로 비운다.
flush()
는 곧 버퍼가 다 차지 않았지만, 출력을 하는 메서드이다.
StringBuilder
와 유사하다. (그냥 StringBuilder 쓰자...)
StringBuilder
https://innovation123.tistory.com/17
4) 예제
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String str = "world!!";
bw.write("hello"+" "+str+"\n");
bw.flush();
bw.write("hello~~");
bw.write(str);
bw.flush();
(출력)
hello world!!
hello~~ world!!
- 중간에
flush()
를 한번 실행하고, 다시 입력받아서 다시 실행했다.
Scanner, System.out.println을 이용한 게 더 간결해 보이지만,
데이터, 속도 측면에서 보면 BufferedReader, BufferedWriter을 사용하는 게 좋다.
입력을 많이 받아야 하는 경우, BufferedReader
를 이용하는 것이 좋다.
알고리즘 문제를 풀 때는BufferedReader
, StringTokenizer
, StringBuilder
조합을 사용하는 것을 추천한다.
백준 11725번 그래프 문제이다.
이 문제에서는 출력을 노드 개수 -1 개 만큼 하고, 최대 노드의 개수는 10만개 이다.
이 문제의 마지막에서는 문제를 풀며 값을 담았던 list의 값들을 한줄에 하나씩 출력한다.
아래(첫번째 제출)은 list를 순회하면서 System.out.println() 으로 출력했을 때이고,
위 (두번째 제출)은 StringBuilder를 선언 한 뒤 list를 순회하며 StringBuilder에 append 하고 마지막에 딱 한번
System.out.println(stringBuilder); 로 출력한 결과이다.
이렇게 출력 방법 차이로 시간 차이가 많이 나게 된다.
만약 여기서 Scanner로 입력받고 첫번째 방법으로 출력한다면 시간은 더 오래 걸릴 것이다.
따라서 위에서 말했듯이 알고리즘 문제를 풀 때는
BufferedReader , StringTokenizer, StringBuilder조합을 사용하는 것을 추천한다.
'JAVA & Spring' 카테고리의 다른 글
[Java] 소켓 프로그래밍(Socket Programming) 예제 / ServerSocket, Socket, Thread 프로그래밍 (0) | 2024.08.09 |
---|---|
[JAVA] 문자열 다루기 String, StringBuilder, StringBuffer (0) | 2023.06.28 |
[JAVA] Comparator / Comparable - 정렬을 위한 클래스(인터페이스) (2) | 2023.06.10 |
[JAVA] 배열의 길이 length에는 괄호()가 붙지 않고, 문자열의 길이 length()에는 괄호()가 붙는 이유 (0) | 2023.06.03 |
[JAVA] Math 클래스 (0) | 2023.06.02 |