전공공부/자바 (JAVA)

[JAVA] Scanner vs BufferedReader & System.out vs BufferedWriter

jooona 2022. 1. 20. 23:27
반응형

Java에는 입출력을 실행하는 여러 방법이 있습니다. 

 

입력의 경우, 가장 유명한 두 방법은 다음과 같습니다.

 

1
2
3
4
5
6
7
// 1. Scanner 
Scanner sc = new Scanner(System.in);
sc.next();
 
// 2. BufferedReader 
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
cs

 

출력의 경우에는 다음과 같습니다. 

 

1
2
3
4
5
6
7
// 1. System.out
System.out.println("hi");
        
// 2. BufferedWriter
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("HI");
bw.flush();
cs

 

입력과 출력에서의 두 방법의 차이에 대해 알아보도록 하겠습니다.

 

사용법의 차이

Scanner의 경우 입력을 스페이스바 또는 엔터키를 모두 입력값의 경계로 인식하고, 입력을 받을 때 nextInt() 등의 메서드를 이용해 데이터 타입을 결정할 수 있어 정말 편리하게 사용할 수 있습니다.

 

System.out의 경우에도 사용이 정말 쉽습니다. 객체를 선언할 필요도 없고 별달리 사용법을 공부할 필요도 없습니다.

 

BufferedReader의 경우 모든 입력을 줄 단위의 String 타입으로 받아오기 때문에 사용자가 알아서 가공을 해주어야 합니다. 그래서 Integer.parseInt, charAt 등의 방법들로 int형, char형 등으로 변환을 하여 사용해야 합니다.

 

BufferedWriter의 경우에도 String 형이 아니면 String.valueOf 등의 방법으로 String화를 해주어야 하며, flush() 메서드를 호출해주어야 실제 출력이 실행되는 번거로움이 있습니다.

 

속도의 차이

하지만 이러한 사용의 불편함에도 불구하고 알고리즘 문제 해결을 할 때 BufferedReader, BufferedWriter를 사용하는 이유가 있습니다. 바로 속도가 Scanner나 System.out에 비해 압도적으로 빠르다는 것입니다.

 

입력과 출력이 비슷한 맥락이기 때문에 출력의 경우를 예시로 사용하겠습니다. System.out은 호출될 때마다 바로바로 모니터에 출력물을 띄워줍니다. 하지만 BufferedWriter의 경우, 버퍼(Buffer)를 이용하여 여러 번의 출력을 모았다가 한 번에 모니터에 띄워주기 때문에 굉장히 많은 시간을 아낄 수 있습니다.

 

더 쉽게 설명하기위해 실생활의 예를 들어보겠습니다. 엄마의 심부름을 할 때, 엄마가 두부 사 오라고 하면 마트에 가서 두부를 사러 갔다 오고, 또 조금 있다가 우유 사 오라고 하면 우유를 사러 갔다 오고, 또 조금 있다가 멸치 사 오라고 하면 또 멸치를 사러 갔다 오는 방식이 바로 System.out이 사용하는 방식입니다. 마트를 무려 3번이나 뛰어갔다 와야 하죠.

 

하지만 BufferedWriter의 경우 두부 사 오라고 하면 메모장에 적어놓고, 조금 있다가 우유 사오라고 하면 또 메모장에 적어놓고, 또 멸치 사 오라고 하면 역시 메모장에 적어뒀다가 한 번에 마트에 다녀오는 격입니다. 실행시간 면에서 굉장한 차이가 나겠죠?

 

실제로 모니터에 출력을 띄우기 위해서는 CPU에 Interrupt를 발생시켜야 하고, 이 작업은 굉장히 비용이 많이 드는 행위이기 때문에 모니터에 자주 출력을 띄우는 System.out의 방식은 굉장히 비효율적입니다.

 

InputStreamReader, OutputStreamWriter

BufferedReader, BufferedWriter는 버퍼를 이용하여 입출력 시간을 단축시키는 역할을 한다는 점을 알게 되었습니다. 그렇다면, BufferedReader, BufferedWriter와 함께 쓰이는 InputStreamReader, OutputStreamWriter는 무슨 역할을 할까요?

 

InputStream(System.in)으로 입력을 받으면 기본적으로 1Byte 단위로 끊어서 읽습니다. 그런데 우리가 아는 char 변수의 크기는 2바이트를 필요로 하죠? 그래서 그냥 1Byte로 끊어서 읽게 되면 원하는 문자를 제대로 입력받을 수 없습니다. 여기서 이 InputStreamReader가 1Byte씩 읽어오던 것을 2Byte씩 읽도록 바꾸어주는 역할을 합니다. OutputStreamWriter는 정확하게 반대의 역할을 하는 것 정도는 유추할 수 있겠죠?

반응형