
프로그래머스 level0을 떼고 🎉, 다양한 유형의 코테를 풀어보고자 백준 문제를 풀기 시작했다.
풀다 보니 프로그래머스 문제들과는 다르게 직접 값을 입력 입력 받아 코드를 짜야하는 문제들이 많았다! 이참에 기본적인 내용들을 정리하고 넘어가보자!! 💪🏻
BufferedReader는 버퍼를 사용하여 읽기와 쓰기를 하는 함수이다.
버퍼를 사용하지 않는 입력: 키보드의 입력이 키를 누르는 즉시 바로 프로그램에 전달됨.
버퍼를 사용하는 입력: 키보드의 입력이 있을 때마다 한 문자씩 버퍼로 전송함. 버퍼가 가득 차거나 혹은 개행 문자가 나타나면 버퍼의 내용을 한 번에 프로그램에 전달한다.
한번 버퍼를 거쳐 출력되는 것보다, 키보드의 입력을 받는 즉시 출력하는 것이 더 빠르지 않을까?! 하고 생각할 수 있다.
하드디크스는 속도가 느리다. 그리고 외부장치(키보드, 모니터 등)와 데이터 입출력도 생각보다 시간이 오래 걸린다. 그렇기 때문에 키보드의 입력이 있을 때마다 바로 이동시키는 것보다는, 중간에 버퍼를 두어 한번에 묶어 보내는 것이 더 효율적이고 빠른 방법이다.
쓰레기통을 비우는 일이라고 생각하면 이해가 쉽다. 쓰레기가 생길 때마다 하나하나 밖에 내다버리는 것보다, 쓰레기통에 하나하나 모았다가 꽉 차면 한 번에 모아서 버리는게 훨씬 효율적인 것과 비슷한 개념이라고 생각하면 된다.
| BufferedReader | Scanner |
|---|---|
| 개행 문자만 경계로 인식한다. | 띄어쓰기와 개행문자를 경계로 입력 값을 인식한다. |
| 입력 받은 데이터가 String으로 고정된다. 따라서 입력 받은 데이터를 원하는 타입으로 가공하는 작업이 필요하다. | 데이터 타입을 따로 가공할 필요가 없다. 지원해주는 메소드가 많고, 사용하기 쉽기 때문에 많이 사용된다. |
| 버퍼 사이즈가 8192 char(16,384 byte)이기 때문에 입력이 많을 때 BufferedReader가 유리하다. | 버퍼 사이즈가 1024 char이기 때문에 많은 입력을 필요로 할 경우에는 성능상 좋지 못한 결과를 불러온다. |
| 동기와 되기 때문에 멀티 스레드 환경에서 안전하다. | 동기화가 되지 않기 때문에 멀티 스레드 환경에서 안전하지 않다. |
Scanner는 띄어쓰기와 개행문자를 경계로 하여 입력 값을 인식한다. 그렇기 때문에 따로 가공할 필요가 없어 편리하다.
가공할 필요가 없다는 것은, 가령 int형 변수를 입력 받고자 하면 int x = scanner.nextInt()를 하용하여 바로 원하는 타입의 입력을 받을 수 있다는 것이다.
하지만, BufferedReader는 입력 받은 데이터가 String으로 고정된다. 따라서 입력 받은 데이터를 원하는 타입으로 가공하는 작업이 필요하다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 선언
String s = br.readLine();
int i = Integer.parseInt(s);
BufferedReader를 통해 읽어온 데이터는 개행문자 단위(Line 단위)로 나뉘어진다.
만약 이를 '공백 단위'로 데이터를 가공하고자 하면 따로 작업을 해주어야 한다.
이 때 사용하는 것이 StringTokenizer나 String.split() 함수이다.
// StringTokenizer
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());
// String.split() 함수
String s = br.readLine();
String arr[] = s.split(" ");
StringTokenizer의 nextToken() 함수를 쓰면 readLine()을 통해 입력 받은 값을 공백 단위로 구분하여 순서대로 호출할 수 있다.
String.spilt() 함수를 사용하면, 배열에 공백 단위로 끊어 데이터를 저장하여 사용할 수 있다.
| Modifier and Type | Method and Description |
|---|---|
| void | close() 입력 스트림을 닫고, 사용하던 자원을 해제 |
| void | mark(int, readAheadLimit) 스트림의 현재 위치를 마킹 |
| int | read() 한 글자만 읽어 정수형으로 변환(e.g. '3'을 읽어 정수형인 (int)'3' = 51로 반환 |
| String | readLine() 한 줄을 읽음 |
| boolean | ready() 입력 스트림이 사용할 준비가 되었는지 확인(1이 준비 완료) |