본문 바로가기

별걸다하는 IT/프로그래밍언어

[Java 자바 입출력] BufferedReader/BufferedWriter

[자바 입출력 함수]

BufferedReader / BufferWriter

BufferedReader/BufferedWriter은 이름처럼 버퍼를 이용해서 읽고 쓰는 함수입니다.

이 함수는 버퍼를 이용하기 때문에 이 함수를 이용하면 입출력의 효율이 비교할 수 없을 정도로 좋아집니다.

 

한 번 거쳐가므로 느릴거 같은 데 왜 빠르냐고요?

하드디스크는 원래 속도가 엄청 느립니다. 하드뿐만 아니라 키보드나 모니터와 같은 외부 장치와의 데이터 입출력은 생각보다 시간이 걸리는 작업이예요. 버퍼링 없이 키보드가 눌릴 때마다 눌린 문자의 정보를 목적지로 바로 이동시키는 것보다 중간에 메모리 버퍼를 둬서 데이터를 한데 묶어서 이동시키는 것이 보다 효율적이고 빠릅니다.

그냥 전송하게 되면 CPU와 성능 갭이 많이 나서 비효율적이예요. 

 

예시를 들자면, 흙을 파서 저 언덕에 버리는데, 한 번 삽질할 때마다 가서 버리는 것보다, 수레에 가득 채워서 한번에 나르는 것이 효율적인 것과 같은 이치입니다. 즉, 모아뒀다가 한 번에 전송하는게 훨씬 더 효율적!

 

 

BufferedReader 

자바를 처음 접하시는 분들은 Scanner를 이용해 입력받는걸 배우는데, 띄어쓰기(스페이스)와 엔터(개행문자)를 경계로 입력 값을 인식하기 때문에 따로 가공할 필요가 없어서 사용하기 매우 편리합니다.

반면에 BufferedReader는 엔터만 경계로 인식하고 받은 데이터가 String으로 고정되기 때문에 데이터를 따로 가공해야 하는 경우가 많죠 ㅎㅎ 그래서 조금 번거로워요 하지만 Scanner에 비해서 상대적으로 빠름!!!  

 

공식 문서에는

Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines. The buffer size may be specified, or the default size may be used. 

입력 스트림에서 문자를 읽는 함수인데 문자나 배열, 라인들을 효율적으로 읽기 위해서 문자들을 버퍼에 저장하고(버퍼링) 읽는 방법을 취한다네요. 버퍼 사이즈는 우리가 지정할 수도 있지만 지정안할 경우에는 기존 디폴트 사이즈가 사용됩니다.

라고 나와있어요

 

따라서 알고리즘 풀 때 BufferedReader를 이용한 해설을 많이 볼 수 있어요. 많은 데이터를 입력받아야 할 상황에서는 BufferedReader를 이용해줍시다!

 

BufferedReader 사용방법

BufferedReader의 readLine()을 사용하면 데이터를 라인 단위로 읽을 수 있어요.

readLine 함수의 리턴 값은 String으로 고정되기 때문에 String이 아닌 다른 타입으로 입력을 받으려면 형변환을 꼭 해줘야 합니다.

import java.io.*;

class BufferedReaderEx1 {
    public static void main(String[] args){
        try{ //예외처리 필수! 또는 throwsIOException해주기
            //콘솔에서 입력 받을 경우
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 

            //파일에서 입력받을 경우
            FileReader fr = new FileReader("BufferedReaderEx1.java"); //"노란색글은 파일 이름"
            BufferedReader br_f = new BufferedReader(fr);
            
            //String이 리턴값이라 형변환 필수! 라인단위임
            int num = Integer.parseInt(br.readLine());             
            br.close(); //입출력이 끝난 후 닫아주기
            
            //파일의 한 줄 한 줄 읽어서 출력한다.
            String line ="";
            for(int i=1; (line = br_f.readLine()) != null; i++){
                System.out.println(line);
            }
        } catch (IOException e){ //
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}

한 줄 한 줄 읽는건 알겠는데 공백단위로 데이터를 알려면 어떻게 해야하냐구요?

Scanner는 공백단위로도 끊어주기 때문에 이런걸 고려할 필요가 없었잖아요!

 

StringTokenizer의 nextToken함수를 이용하거나 String클래스의 split함수를 이용하는 방법이 있습니다. 

 

BufferedReader클래스의 또 다른 메인 함수들

Modifier and Type

 Method and Description

 void

 Close()
 Closes the stream and releases any system resources associated with it.

 입력스트림을 닫고 사용하던 자원들을 풀어요.

 void

 mark(int, readAheadLimit)
 Marks the present position in the system.
 스트림의 현재 위치를 마킹합니다.

 boolean

 markSupported()

 Tells whether this stream supports the mark() operation, which it does.

 스트림이 mark 기능을 지원하는지 true/false로 알려줍니다.

 int

 read()

 Reads a single character.

 한 글자만 읽어 정수형으로 반환해줍니다.
 즉 3을 '3'이라고 읽어서 '3'의 정수형인 (int)'3' =51을 반환
 3을 친다고 해서 3을 리턴해주는 메서드가 아니예요
 int

 read(char[] cbuf, int offset, int length)
 Reads characters into a portion of an array.
 cbuf의 offset위치부터 length길이만큼 문자를 스트림으로부터 읽어옵니다.

 String

 readLine()
 Reads a line of text.

 한줄을 읽어요 String으로 반환!
 boolean  ready()
 Tells whether this stream is ready to be read.
 입력스트림이 사용할 준비가 되어있는지 확인해줘요 1이면 준비완료겠죠?

 void

 reset()

 Resets the stream to the most recent mark.

 마킹이 있으면 그 위치부터 다시 시작, 그렇지 않으면 처음부터 다시 시작합니다.

 long

 skip(long n)

 Skips characters.

 n개의 문자를 건너뜁니다.

 

BufferedWriter

마찬가지로 우리가 매번 배우는 System.out.print("");과 동일하게 사용가능한 함수입니다.

BufferedWriter 함수 또한 버퍼를 이용하기 때문에 성능면에서 더 좋아요. 많은 양의 출력이 필요할 때에는 마찬가지로 요 아이를 이용해주는 것이 좋습니다.

System.out.println처럼 함수가 문자열출력과 개행을 동시에 해주지 않기 때문에 개행을 하려면 write에 "\n"를 넣어주거나 newLine함수를 사용해야합니다. 

import java.io.*;
 
class BufferedWriterEx1 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("bufferedWriter.txt"));
        bw.write("hello\n"); //출력
        bw.newLine(); //개행 즉 엔터 역할
        bw.write("I am writing\n"); //개행과 함께 출력
        bw.flush(); //남아 있는 데이터를 모두 출력
        bw.close(); //스트림 
    }
}

버퍼를 이용하는 거기 때문에 다 쓴 뒤에는 버퍼를 클린하게 해줘야 합니다.

flush()함수를 통해서 버퍼에 남아있는 데이터를 출력해 없앤 후,

스트림을 닫아줘요 

 

BufferedWriter클래스의 또 다른 메인 함수들

 Modifier and Type

 Method and Description

 void

 close()

 Closes the stream, flushing it first.

 스트림을 닫습니다. 닫기 전에 flushing해주세요.

 void

 flush()

 Flushes the stream.

 스트림을 비웁니다.  

 void

 newLine()

 Writes a line separator.

 개행역할을 합니다. 

 void

 write(char[] cbuf, int offset, int length)

 버퍼 offset위치부터 length크기만큼 write 씁니다.

 void

 write(int c)

 Writes a single character

 한 글자 쓰기 

 void

 write(String s, int offset, int length)

 Writes a portion of a String

 문자열에서 offset부터 일정 길이만큼 write 써줘요

 

PrintWriter, FileWriter, OutputStreamWriter, StringTokenizer, String 등의 클래스와 함께 공부하면 좋습니다!

 

풀어보면 좋은 문제:

반복문 N찍기

사칙연산

 

여기까지!