-
자바(Java) BufferedReader 클래스ProgrammingLanguage/Java 2021. 1. 18. 23:53
자바의 BufferedReader 클래스를 사용하기 전에, 먼저 스트림(Stream)의 개념과, Scanner 클래스에 대해 먼저 간단히 이해 하는 것이 좋다. 잘 모른다면 아래 글을 참고하여 이해하도록 하자.
*vs. Scanner
->BufferedReader 와 Scanner 클래스는 대표적인 Java의 문자열을 입력받는 클래스이다. 특히 알고리즘 문제 풀이시 대용량 데이터를 처리하는 경우, BufferedReader 클래스를 많이 사용하기 때문에, 우선은 알고리즘 문제 풀이시 참고할만한 수준에서 이 두 클래스의 용도를 구분하면 다음과 같다.
(1) 수행 시간(속도) 측면 : BufferedReader가 Scanner 클래스에 비하여 더 빠르게 입력을 처리할 수 있다.
※BufferedReader는 Scanner 클래스에 비해 더 큰 Buffer Size를 가지고 있으며, BufferedReader 클래스는 문자열을 단순히 읽어 들이는 방식이지만 Scanner 클래스는 문자열을 읽어 많은 정규식과 함께 구문 분석을 하는 용도로 사용되기 때문에 수행 시간의 차이가 발생한다! 정도로만 우선 알아두도록 하자.
(참고 : stackoverflow.com/questions/2231369/scanner-vs-bufferedreader).
※Buffer에 의한 수행 시간 차이 : Buffer는 데이터를 편리하게 이동시켜주는 수단이라고 생각하면 이해하기 좋다. 데이터를 스트림을 통해 이동한다고 하였는데, 이 데이터의 이동 자체가 자원이 드는 행위이다. 일상 생활에서 한 번에 많은 사람을 효율적으로 이동시키기 위하여 버스와 지하철을 이용하듯이, Buffer Size에 따라 한 번에 이동 시킬 수 있는 데이터의 양이 달라진다. 따라서, Buffer Size가 더 큰 BufferedReader 클래스가 더 빠른 처리 속도를 가지고 있는 것이다.
(2) 사용성 측면 : Scanner 클래스가 BufferedReader 클래스에 비해 문자열을 파싱하는 여러 기능을 많이 가지고 있기 때문에, 사용하기 편하다.
->쉽게 말해 간단한 문제의 경우 Scanner 클래스를 이용하여 간단하게 처리하면 되지만, 알고리즘 문제를 풀 때 많은 입력 데이터로 인한 수행 시간 과부하를 방지하기 위해서는 BufferedReader 클래스를 사용해야 한다.
*BufferedReader 클래스(알고리즘 문제에서 사용되는 예시)
->처음 사용하기는 까다롭지만 바이트 스트림과 문자 스트림, 그리고 버퍼에 대한 이해를 바탕으로 아래 단계를 이해하였다면 이후에는 암기하여 빠르게 입력 데이터를 처리하는 연습을 하도록 하자.
(1) InputStreamReader 클래스 이용 : 이 클래스는 바이트 스트림과 문자 스트림을 연결시켜주는 다리 역할을 한다. 표준 입력(System.in)은 InputStream 형태로 지정되어 있으며, InputStream은 바이트 단위 입력 스트림의 취상위 클래스이다. 즉, 바이트 스트림인 System.in을 InputStreamReader 클래스를 이용하여 문자 스트림으로 변경시키는 작업을 먼저 해주어야 한다.
InputStreamReader in = new InputStreamReader(System.in);
(참고1. docs.oracle.com/javase/7/docs/api/java/io/InputStream.html).
(참고2. docs.oracle.com/javase/7/docs/api/java/lang/System.html).
(2) BufferedReader 클래스 이용 : InputStreamReader 클래스를 이용해 변환된 문자 스트림을 버퍼 스트림에 저장 시킨다(쉽게 말해, 데이터를 버퍼라는 상자에 가공하여 적재시키는 단계).
BufferedReader br = new BufferedReader(in);
보통 앞선 1, 2 단계를 합쳐 아래와 같이 간단하게 작성한다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
(3) 적재된 데이터를 불러온다 : BufferedReader의 내부 메서드를 이용하여 데이터를 읽어온다. 보통 알고리즘 문제에서는 1라인 단위 스트링 데이터로 많이 불러오기 때문에 readLine() 메서드를 많이 사용한다.
(BufferedReader 메서드 참고 : docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html)
String line = br.readLine();
(4) 적재된 데이터를 가공한다 : 앞선 단계는 스트림을 적절히 변환 시키고, 적재된 데이터를 한 줄씩 불러오는 과정에 불과하다. 하지만 대부분의 알고리즘 문제를 푸는 경우, 불러온 데이터를 적절히 가공하여 사용하는 것이 주된 목표이다. 아래 두 방법은 보통 알고리즘 문제에서 BufferedReader에 적재된 데이터를 readLine() 메서드를 활용하여 한 줄 String 단위로 불러오고, 해당 라인 내에서 '특정 문자'를 기준으로 데이터들을 분류하여 해석해야되는 경우가 많기 때문에 사용하는 것임을 알아두자. 즉, StringTokenizer 클래스와 String.split() 메서드는 한 줄 String 데이터를 '특정 문자'를 기준으로 분류하기 편하기 때문에 사용하는 것이다.
(4 - 1) StringTokenizer 클래스 이용 : 생성된 객체에 특정 문자를 기준으로 문자열을 분리하여 토큰 단위로 저장하고, 메서드를 이용해 저장된 문자열을 원하는 대로 불러올 수 있다.
(StringTokenizer 메서드 참고 : docs.oracle.com/javase/7/docs/api/java/util/StringTokenizer.html).
Ex) StringTokenizer를 이용한 데이터의 가공과 사용 예.
package practice; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.StringTokenizer; public class BufferedReaderTest { public static void main(String[] args) throws Exception { // 바이트 스트림인 System.in을 InputStreamReader 클래스를 이용하여 문자 스트림으로 바꾼다. // 바꾼 문자 스트림을 BufferedReader 클래스를 이용하여 버퍼 스트림으로 바꾼다. BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 버퍼 스트림에서 한 줄(Line) String 데이터를 불러온다. // 불러온 String 데이터를 공백을 기준으로 토큰단위로 나눈뒤 저장한다. StringTokenizer st = new StringTokenizer(br.readLine()); // hasMoreTokens() 메서드를 이용하여 st객체에 문자열이 남아있는지 확인한다. while(st.hasMoreTokens()) { // 남아있는 토큰을 하나씩 불러온다. String word = st.nextToken(); System.out.print(word + " "); } } }
※만일 불러온 토큰 데이터를 정수로 변환하고 싶은 경우, Wrapper 클래스인 Integer 클래스를 적절히 활용하여 데이터를 가공할 수 있다!
(4 - 2) String.split() 메서드 이용 : StringTokenizer 클래스와 마찬가지로 String.split() 메서드 또한 특정 문자를 기준으로 문자열을 분리하여 토큰 단위로 저장할 수 있다. 다만, 특정 배열을 생성하여 저장하여야하고, 해당 배열의 인덱스를 참조해서 불러오는등의 번거로움이 존재한다.
package practice; import java.io.BufferedReader; import java.io.InputStreamReader; public class BufferedReaderTest { public static void main(String[] args) throws Exception { // 바이트 스트림인 System.in을 InputStreamReader 클래스를 이용하여 문자 스트림으로 바꾼다. // 바꾼 문자 스트림을 BufferedReader 클래스를 이용하여 버퍼 스트림으로 바꾼다. BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 버퍼 스트림에서 한 줄(Line) String 데이터를 불러온다. // 불러온 String 데이터를 공백을 기준으로 나눈뒤 String 타입의 list 배열에 저장한다. String[] list = br.readLine().split(" "); // list 배열에 접근하여 데이터를 불러온다. for (int i = 0; i < list.length; i++) { System.out.println(list[i]); } } }
'ProgrammingLanguage > Java' 카테고리의 다른 글
자바(Java) 싱글턴 패턴(Singleton Pattern) (1) 2021.01.23 스트림(Stream)과 자바(Java)의 Scanner 클래스 (0) 2021.01.14 깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy) (0) 2021.01.13