Step-by-Step

[Java / 입출력] BufferedReader / BufferedWriter 본문

언어/JAVA

[Java / 입출력] BufferedReader / BufferedWriter

희주(KHJ) 2021. 6. 10. 21:54

백준 사이트에서 프로그래밍 문제를 풀면 입력 값을 받기위해 Scanner를 꼭 이용한다

처음으로 배웠던 입력 방식이다 보니 가장 익숙하고 쓰기 간편해서 아직까지 쓰고 있었다

그동안 아무 문제 없이 사용했으나 점점 난이도가 높아질수록 Scanner를 사용하면 시간 초과가 발생하기 시작하였다

밑은 조금 전에 끝낸 따끈따끈한 실패작이다~! 하핫

백준 1406 에디터

이전에는 시간이나 메모리 제한도 여유로워서 출력만 제대로 되면 성공했는데, 더이상 그럴수 없게 됐다

코드에서 가장 중요한 것은 알고리즘! 알고리즘에서 가장 중요한 것은 효율성이다 

※ 알고리즘 정의 포스팅 : https://smile-development.tistory.com/8

이제 효율적인 코드를 작성하기 위해 Scanner에 대한 집착?고집?을 놓아줄 필요가 있다 ㅠ_ㅠ

그렇게 검색해서 나온 방법이 BufferedReader이다

Scanner와 같은 Java 입력 함수이고, 이름처럼 버퍼(Buffer)를 이용하여 읽고 쓰는 함수이다

그렇담 우선 버퍼가 무엇인지부터 알아보았다 대략 개념만 파악하였다

 

Buffer

데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 메모리 영역

보통 데이터는 키보드와 같은 입력 장치로부터 받거나 프린터와 같은 출력장치로 내보낼 때 버퍼에 저장됨

버퍼는 들어온 순서대로 출력하는 FIFO 방식을 사용

출처 : https://tcpschool.com/cpp/cpp_io_streamBuffer

 

Buffering

버퍼를 활용하는 방식 또는 버퍼를 채우는 동작으로, 다른 말로 큐(Queue)라고도 표현

 

BufferedReader

java.io 에 있는 클래스로 사용자가 요청할 때마다 데이터를 읽어오는 것이 아닌

일정 크기의 데이터를 한 번에 읽어와 버퍼에 보관한 후 사용자의 요청이 있을 때 버퍼에서 데이터를 읽어오는 방식

API 문서를 꼭 읽어보자! https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html

 

BufferedReader 사용법

위에 링크에 있는 API 문서를 읽어보면 BufferedReader의 클래스 구조가 다음과 같다

public BufferedReader(Reader in, int sz)

여기서 in은 Reader를 의미하고 sz는 Input-Buffer size를 의미하는데, 생략하면 알아서 default 값으로 들어간다

연결된 Reader 문서로 들어가면 Reader는 문자 스트림을 읽기 위한 추상 클래스라 나와있다

가장 대표적인 Reader로는 InputStreamReader가 있다

InputStreamReader 문서로 들어가면 바이트 스트림에서 문자 스트림으로 가는 다리라고 나와있다

공식 문서에도 효율성을 극대화하기 위해 BufferedReader 내에 InputStreamReader를 사용하는게 좋다고 한다

※ BufferedWriter도 BufferedReader와 유사하기 때문에 생략하였다

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		String s = br.readLine();
		int i = Integer.parseInt(br.readLine());
		
		bw.write(s+"\n");
		bw.write(i+"\n");
		bw.flush();
		bw.close();
	}
}

BufferedReader와 InputStreamReader로 입력받고, BufferedWriter와 OutputStreamWriter로 출력했다

화면상으로 입출력하기 위해 System.in과 System.out을 이용하였다 (Scanner때도 사용)

BufferedReader를 이용하기 위해서는 무조건 예외처리를 해줘야 하고 (throws IOException 또는 try catch)

BufferedWriter를 이용하기 위해서는 마지막에 flush()와 close()로 닫아주어야 한다

그리고 추가로 BufferedWriter의 write 메소드는 개행을 하지 않는다 필요하면 위의 코드처럼 작성하자

※ 예시에서는 Reader와 Writer 두 개 다 사용했으나 필요에 따라 골라쓰면 된다

 

Scanner와 BufferedReader의 차이점

가장 큰 차이점은 바로 시간이다!!!  import를 5개나 하면서 이것을 쓰는 이유!!!!!!

BufferedReader는 Scanner보다 Buffer Size도 훨씬 크고 입력을 Line 단위로 받아

버퍼에 저장 후 한 번에 보내며 별도의 캐스팅 과정이 없어서 빠른 속도로 처리할 수 있다

BufferedReader의 특성이 속도 부분에서는 매우 큰 장점을 가지고 있지만 

Scanner의 특성은 속도가 낮은 대신 다른 장점들도 많이 가지고 있다

기존에 사용했던 Scanner은 공백(띄어쓰기)와 개행(Enter) 둘 다 입력값의 경계값으로 인식할 수 있어

문자열 파싱에 용이하며 작은 버퍼로도 충분하다

또한 데이터를 입력받을 때 데이터 타입을 결정해 나중에 따로 캐스팅 작업을 하지 않아도 된다


참조1 : https://machine-geon.tistory.com/79?category=871701

참조2 : http://dawoonjeong.com/java-scanner-vs-buffered_reader/

참조3 : https://jhnyang.tistory.com/92

 

 

Comments