본문 바로가기
Back-end/Java_T.I.L

[TIL 220118] BufferedReader / BufferedWriter

by 사장님나빠여 2022. 1. 19.

백준 단계별 문제 풀이 중 for문 문제 중 15552번에서 컴파일 시간을 줄이기 위해

Scanner 대신 BufferedReader와 BufferedWriter를 사용하라고 하는데

아직 거기까지 진도를 못나갔기 때문에 블로그에 TIL로 따로 정리를 해보려고 한다.


BuffedReader / BufferedWriter는 이름처럼 버퍼를 이용해서 읽고쓰는 함수다. 이 함수는 버퍼를 이용하기 때문에 이 함수를 이용하면 입출력의 효율이 비교할 수 없을 정도로 좋아진다. BufferedReader의 readLine()을 사용하면 데이터를 라인단위로 읽을 수 있고 BufferedWriter는 newLine()이라는 줄바꿈 해주는 메서드를 가지고 있다.

 

BufferedReader가 Scanner보다 빠른 이유

BufferedReader가 Scanner보다 빠른 이유는 버퍼를 이용하기 때문이다.

 

입력도 사용자가 키보드에 누를 때마다 전달을 하는 것이 아니라 버퍼에 용량만큼 모았다가 전달해주는 것이다. 생각해보면 내가 현재 위치에서 10m 떨어진 곳에서 어떤 물건을 옮겨야하는데 하나씩 옮기는 것보단 한번에 최대로 옮길 수 있는 만큼을 옮겨야 덜 힘들고 빠를 것이다.

출력도 마찬가지로 버퍼를 거쳐서 간접적으로 출력장치로 전달되기에 시스템의 데이터처리 효율성을 높여주며 버퍼스트림을 InputStreamReader / OutputStreamWriter를 같이 사용하여 버퍼링을 하게 되면 입출력 스트림으로부터 미리 버퍼에 데이터를 갖다 놓기 때문에 보다 효율적인 입출력이 가능하다.

 

1. BufferedReader

Scanner를 통해 입력을 받을경우 SpaceBar, Enter를 모두 경계로 인식하기에 입력받은 데이터를 가공하기 매우 편리하다. 하지만 그에 비해 BufferedReader는 Enter만 경계로 인식하고 받은 데이터가 String으로 고정되기 때문에 입력받은 데이터를 가공하는 작업이 필요할 경우가 많다. 하지만 많은 양의 데이터를 입력받을 경우 BufferedReader를 통해 입력받는 것이 효율면에서 훨씬 낫다. Buffer를 이용했기 때문에 왜 더 빠른지는 위의 설명에서 알 수 있다.

 

[사용방법]

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

public class Test{
	public static void main(String[] args) throws IOException{
    	/*아래 코드는 원래
        InputStream is = System.in;
		Reader reader = new InputStreamReader(is);
		BufferedReader br = new BufferedReader(reader);
        이렇게 쓰인다.
        */
    	BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        String s = bf.readLine();
        int i=Integer.parseInt(s);
    }
}

 

첫번째는 BufferedReader의 readLine()을 사용하면 데이터를 라인 단위로 읽을 수 있다. Scanner에서 nextLine()과 같다. readLine 함수의 리턴 값은 String으로 고정되기 때문에 String이 아닌 다른 타입으로 입력을 받으려면 꼭 형변환(parse.변환형식)을 꼭 해줘야 한다.

 

두번째는 예외처리를 꼭 해주어야 한다는 점이다. readLine을 할 때마다 try & catch를 활용하여 예외처리를 해주어도 되지만 대개 throws IOException을 통하여 작업한다. import문에도 예외를 기재해주어야 한다  

 

※입력을 여러개 받아야 하는 상황

StringTokenizer클래스 또는 String클래스의 메서드인 split()을 이용해서 공백을 기준으로 나누면 된다.

 

StringTokenizer클래스란?

String : 문자열을 Tokenizer : 토큰화한다.

토큰은 분리된 문자열 조각으로, StringTokenizer클래스는 하나의 문자열을 여러개의 토큰으로 분리하는 클래스

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
 public class Test{
 	public static void main(String[] args){
    	BufferedReader bf = new BfferedReader(new InputStreamReader(System.in));
        String s = bf.readLine();
        StringTokenizer st = new StringTokenizer(s);
        
        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        
        String[] arr = s.split(" ");
        System.out.println(a);
        System.out.println(b);
        
        for(String k : arr){
        	System.out.print(k)
        }
    }
}

readLine()메서드를 이용해서 입력을 받으면 한 줄을 입력으로 받기 때문에 a b와 같이 공백을 넣어서 입력을 해도 공백을 포함해서 버퍼에 넣는다. 그래서 공백을 기준으로 나누기 위해서는 첫번째로 StringTokenizer클래스를 이용하고 두번째로 split(" ")메서드를 이용해서 입력받은 문자를 나눈다.

 

-BufferedReader클래스의 메서드

메서드명 기능
void close() 입력스트림을 닫고 사용하던 자원을 해제한다
String readLine() 한 줄을 읽고, String으로 반환한다
blloean ready() 입력스트림이 사용 준비가 되었는지 확인한다. 1 or true면 준비 완료
int read() 한 글자만을 읽어 정수형으로 반환한다. 단 3을 '3이라 읽기 떄문에 정수형인 (int)'3'
즉 51이 반환된다. 숫자 3을 리턴해주는 메서드가 아니다.
int read(char[] buf) 문자 배열의 buf 크기만큼 문자를 읽어들인다. 읽어 들인 문자 수를 리턴
void newLine() 줄 바꿈 문자열 출력
void flush() 남아있는 모든 데이터를 출력시킨다

 


 

2. BufferedWriter

System.out.print("");와 같이 동일한 기능인 출력을 하는 메서드이다. BufferedWriter 함수 또한 버퍼를 이용하기 때문에 성능이 print메서드보다 좋다. 많은 양의 출력을 할 때는, 입력과 동일하게 버퍼를 사용하는 것이 좋다.

 

[사용방법]

import java.io.BufferedWriter;
import java.io.OutputStreamWriter;

public class Test{
	public static void main(String[] args){
    	BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        String str = "abcdef"; //출력할 문자열
        bw.write(s); //출력
        bw.newLine(); //줄바꿈
        bw.flush(); //남아있는ㄷ ㅔ이터 모두 출력
        bw.close();
    }
}

BufferedWriter는 System.out.print(" "); 처럼 출력과 개행을 동시에 해주지 않기 때문에, 개행을 위해선 따로 newLine(); 혹은 bw.write("\n");을 사용해야 한다. BufferedWriter의 경우 버퍼를 잡아놓았기 때문에 반드시 사용한 후에 flush()와 close()를 해주어야 한다. close()를 하게되면, 출력 스트림을 아예 닫아버리기 때문에 한번 출력후, 다른 것도 출력하고자 한다면 flush()를 사용하면 된다.

 

-BufferedWriter클래스의 메서드

메서드 기능
void close() 스트림을 닫는다
void flush() 스트림을 비운다. 남아있는 데이터를 모두 출력
void newLine() 개행문자를 출력한다. 줄바꿈 
void write(char[] cbuf, int offset, int length) 버퍼offset위치부터 length크기만큼 출력한다
void write(int c) 한 글자를 출력한다
void write(String s, int offset, int length) 문자열에서 offset부터 length만큼 출력한다

댓글