-
더 빠르게 입력받고 출력해보자 BufferedReader/BufferedWriterKnowledge/Java 2019. 9. 4. 22:11반응형
알고리즘 문제를 풀 때 가장 좋은 입출력 방법은? (C, C++, Java ) ( https://takeknowledge.tistory.com/43 )에도 포스팅했지만 java에서 가장 빠르게 입벽받고 출력할 수 있는 방법은 BufferedReader 와 BufferedWriter를 사용하는거다.
입력 속도 비교 ( https://www.acmicpc.net/blog/view/56 ) 에 따르면
첫째 줄에 정수의 개수 N (= 10,000,000)
둘째 줄부터 N개의 줄에 한 개의 자연수(10,000 이하)가 적힌 파일을 입력받는데
java에서 무언가를 입력받을 때 주로 쓰는 Scanner는 4.8448초가 걸렸지만
BufferedReader, Integer.parseInt 를 활용했을 때는 0.6585초가 걸렸을 정도로 차이가 크다.
또한 출력 속도 비교 ( https://www.acmicpc.net/blog/view/57 ) 에 따르면
총 N개의 줄에 1부터 10,000,000까지의 자연수를 한 줄에 하나씩 출력하는데
java에서 무언가를 출력할 때 System.out.println(i); 은 무려 30.013초가 걸렸지만
BufferedWriter, bf.write(i + "\n"); 를 사용했을 때는 0.9581초가 걸렸을 정도로 이 역시 차이가 크다.
결론적으로, JAVA로 수행 시간이 중요한 알고리즘 문제를 풀때는
Scanner와 System.out.println을 쓰는 것 보다는 BufferedReader/BufferedWriter를 활용하는 게 훨씬 좋다는 얘기
사용법도 뭐 Scanner와 System.out.println을 쓸때보다는 번거롭지만 그렇게 까지 복잡하진 않다.
정수 하나를 입력받고 출력하는 예제를 예로 들어보자면
12345678910111213import java.util.Scanner;public class inputOutput {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int i = scanner.nextInt();System.out.println(i);}}이처럼 구현할 수 있지만 이를 BufferedReader/BufferedWriter를 활용하는 방식으로 바꿔보자면
12345678910111213141516171819202122232425262728293031323334353637383940414243import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;// BufferedReader 와 BufferedWriter를 사용하기 위해 필요한 것들// 모두 java.io 패키지에 있는 걸 알 수 있다.// 따라서 애초에 java.io.* 를 import하고 시작하길 권장한다.public class inputOutput {public static void main(String[] args) throws IOException {// bufferedReader로 문자열을 입력 받으면 try~catch로 예외 처리를 해줘야 한다.// 그러나 입력받을 때마다 매번 예외처리하는 건 귀찮은 일..// 사용하는 메소드에 IOException을 throws해 예외처리를 위임하길 권장한다BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));String s = bufferedReader.readLine();// readLine 메소드는 String 값만 받을 수 있다.int i = Integer.parseInt(s);// 따라서 int 형으로 활용하고 싶다면 형변환이 필요하다bufferedReader.close();// reader를 사용후엔 스트림을 닫아주자!BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));bufferedWriter.write(i+"\n");// bufferedWriter 는 System.out.println 처럼 자동 개행 처리가 되지 않기 때문에 개행 처리를 따로 해줘야한다.// bufferedWriter.newLine(); 을 활용하면 개행처리가 가능하나 이건 "\n"에 비해 속도가 느리다고 하니// "\n" 을 활용해 개행처리를 하는 걸 권장한다. 또한 여기엔 하나의 장점이 더 있는데// bufferedWriter.write(i); 처럼 writer에 int를 넣으면 아스키 코드에 따른 char형 값이 출력된다.// 그러나 i와 개행 처리 문자열 "\n" 을 더하면 String 으로 자동 형변환 되기 때문에// 저장되어 있는 int 값 그대로 출력이 가능하다. 여러모로 이 편이 좋다는 얘기bufferedWriter.flush();// 다 사용했으면 남아있는 데이터를 모두 출력시키고bufferedWriter.close();// 스트림을 닫아주면 된다.}}위와 같다. 확실히 코드가 길지만 주석으로 주저리 달아놓은 포인트들을 정리하자면 아래와 같다.
BufferedReader 와 BufferedWriter를 사용하려면
1. import java.io.*; 선언
2. throws IOException 으로 사용하는 메소드에 예외처리를 위임해라 ( try ~ catch로 해도 되지만.. )
3. readLine() 은 String만 리턴한다. 다른 자료형으로 활용하려면 형변환해라.
4. reader도 writer도 사용후엔 스트림을 닫아주자.
writer는 닫기전에 flush를 활용해 남아있는 데이터를 모두 출력시켜야한다.
5. 개행처리는 +"\n"을 활용하는 걸 추천한다. newLine() 을 활용할 수도 있지만 개행문자와 비교하면 속도가 느리고
다른 자료형을 출력할 땐 String으로 형변환도 해주니
int를 출력했는데 아스키 코드 숫자에 해당하는 문자가 출력되는 일을 막아줄 수도 있다.
반응형'Knowledge > Java' 카테고리의 다른 글
JAVA - 증감 연산자를 앞에 붙일 때와 뒤에 붙일 때의 차이! ( 선위 증감연산자 / 후위 증감연산자 ) (0) 2019.10.10 Java 상수 ( final은 무엇인가 ) (0) 2019.10.10 Java 변수, 리터럴, 자료형, 형변환 (0) 2019.10.09 Java에서 날짜를 편하게 쓰자! LocalDate (0) 2019.09.04