Java/코딩테스트

[Java] 코딩테스트 BufferedReader, BufferedWriter 을 쓰는 이유

sh1mj1 2023. 5. 21. 18:10

코딩 테스트를 보다가 어떠한 문제의 답에서 Scanner 와 System.out.print 함수를 사용하지 않고 BufferedReader 와 BufferedWriter 을 사용하는 것을 발견했습니다.

 

그런데 왜 이 두 클래스를 사용해야 하는 것일까요?

그래서 InputStream 부터, InputStreamReader, BufferedReader 을 알아보려고 합니다. 물론 OutputStream, OutputSreamReader, BufferedWriter 도 알아보구요. 

 

그리고 코딩테스트에서 BufferdReader 와 BufferedWriter 을 사용해야 하는 이유도 알아봅시다.

 

 

InputStream / OutputStream

  • 바이트 단위 입출력을 위한 최상위 입출력 스트림 클래스

 

InputStream

바이트 input stream 을 나타내는 모든 클래스의 super class, abstract class.

InputStream 의 subclass 을 정의해야 하는 App. 은 항상 input 의 다음 바이트를 반환하는 메소드를 제공해야 합니다.

InputStream 객체는 1byte 단위 처리 스트림입니다. 그래서 문자 중에서 한글은 처리 불가능하고, 영어 대소문자, 숫자, 특수문자를 처리할 수 있습니다.

public class StreamTest {
    public static void main(String[] args) {

        InputStream is = System.in;
        System.out.println("입력: ");

        try{
            int code = is.read(); // 입력한 키의 코드값 알아오기
            System.out.println(code);

            char ch = (char) code; // 코드값에 대응하는 문자 얻어내기
            System.out.println("char: " + ch);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.println("main method ended");

    }
}

입력: a
97
char: a
main method ended

 

System 클래스 안에 inputStream 을 가지고 있습니다.

public static final InputStream in = null;

 

표준 inputStream 이고 이 stream 은 input data 을 제공하기 위해 open 되어 있으며 준비되어 있습니다. 일반적으로 이 stream 은 키보드의 input 과 일치합니다.

 

OutputStream

바이트의 output stream 을 나타내는 모든 클래스의 super class, abstract class

OutputStream 의 subclass 을 정의해야 하는 App. 은 항상 최소한 output 의 한 바이트를 쓰는 메서드를 제공해야 합니다.

 

public class OutputStreamTest {
    public static void main(String[] args) {

        // System 클래스의 out 이라는 static 필드에는 콘솔창에 출력할 수 있는 PrintStream 객체의 참조값이 들어있음.
        PrintStream ps = System.out;

        // 학습을 위해 PrintStream 객체를 부모 타입 OutputStream 으로 받아오기
        // OutputStream 도 1byte 처리 스트림임.
        OutputStream os = ps;

        try {
            // 출력은 flush() 까지 호출해야 출력이 됨.
            os.write(97);
            os.write(98);
            os.write(99);
            os.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

PrintStreamOutputStream 의 자식입니다. (FileOutputStreamOutputStream 의 자식, PrintStreamFileOutputStream 의 자식)

 

기본적으로 OutputStreamwrite 을 하면 바로 출력되는 것이 아닌 어떤 출력Buffer 에 저장을 합니다. 그러다가 전부 채워지게 되면 출력이 되겠죠? flush() 는 쉽게 말해서 출력 버퍼가 전부 차있던 말던 내보내어 출력하게 만드는 것입니다.

 

InputStreamReader / OutputStreamWriter

  • 문자 단위 입출력을 위한 하위 스트림 클래스

 

InputStreamReader

public class InputStreamReaderTest {
    public static void main(String[] args) {

        InputStream is = System.in;

        InputStreamReader isr = new InputStreamReader(is);

        try {
            System.out.println("입력: ");
            // 한글의 코드값도 읽을 수 있음.
            int code = isr.read();
            System.out.println("code:" + code);

            // 코드값에 대응되는 문자 얻어내기
            char ch = (char) code;
            System.out.println("char: " + ch);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

입력:

code:44032
char: 가

 

InputSteamReader 는 InputStream 보다 향상된 처리 스트림이라고 보면 됩니다. 1byte 가 아닌 2byte 을 처리할 수 있기 때문에 한글도 처리가능합니다.

OutputStreamReader

public class OutputStreamWriterTest {
    public static void main(String[] args) {

        // System 클래스의 out 이라는 static 필드 -> PrintStream 객체의 참조값을 가짐.
        PrintStream ps = System.out;

        // PrintStream 객체를 부모 타입 OutputStream 으로 받아오기.
        // OutputStream : 1byte 처리 스트림
        OutputStream os = ps;

        // 2byte 처리 스트림
        OutputStreamWriter osw = new OutputStreamWriter(os);

        try {
            osw.write(44032);
            osw.write("\n");
            osw.write("한글 입력함");
            osw.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}


한글 입력함

 

OutputStreamWriter 는 OutputStream 보다 향상된 처리 스트림입니다. 2byte 을 처리할 수 있어 한글도 처리 가능합니다.

 

BufferedReader / BufferedWriter

  • 버퍼를 이용한 입출력을 위한 하위 스트림 클래스

 

public class BufferedReaderTest {

    public static void main(String[] args) {
        InputStream is = System.in; // 1 byte 처리 스트림

        InputStreamReader isr = new InputStreamReader(is); // 2byte 처리 스트림

        BufferedReader br = new BufferedReader(isr); // 기능이 더 향상된 Reader

        try {
            System.out.println("문자열 한 줄 입력: ");

            String line = br.readLine(); // 여기서 키보드로 입력을 받음
            System.out.println("입력한 문자열: " + line);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

문자열 한 줄 입력:
제가 입력하고 있는 문자열입니다.
입력한 문자열: 제가 입력하고 있는 문자열입니다.

 

 

BufferReader 는 Java의 Scanner 보다 8배정도 빠를 뿐만 아니라 C 의 scanf 보다도 빠릅니다!

 

BufferedWriter

public class BufferedWriterTest {
    public static void main(String[] args) {
        // System 클래스에 out 이라는 static 필드.
        // 콘솔 창에 출력할 수 있는 PrintStream 객체 참조값이 들어있음
        PrintStream ps = System.out;

        OutputStream os = ps; // 1 byte 처리 스트림
        OutputStreamWriter osw = new OutputStreamWriter(os); // 2 byte 처리 스트림

        BufferedWriter bw = new BufferedWriter(osw);

        try {
            bw.write("하나 \n");
            bw.write("둘");
            bw.newLine(); // 개행 기호를 출력해주는 메소드가 있음.
            bw.write("셋");
            bw.flush();
            bw.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

하나

 

bw.flush() : 버퍼에 잔류하는 모든 바이트를 출력.

bw.close() : 사용한 시스템 자원을 반납하고 출력스트림을 닫는 메소드.

 

 

System.out.println 함수는 BufferedWriter 을 사용한 출력보다 약 3배정도 느립니다.

하지만 BufferedWriter 는 C 의 fwrite 보다는 느리지만 굉장히 빠른 속도를 보여줍니다.

 

대부분의 문제에서는 보통 입력, 출력에 대한 시간은 시간초과를 하지 않고 보정을 해준다고 합니다. 하지만 정말 간혹가다가 보정을 해주지 않고 시간초과(오답) 처리를 하는 경우가 있다고 해요! 

 

코딩테스트에서 시간이 중요한 문제에서는 이렇게 BufferedReader 와 BufferedWriter 을 사용해야 겠네요

 

[JAVA] 입출력스트림의 모든 것, 예제 - InputStream, OutputStream, InputStreamReader, OutputStreamWriter , BufferedReader, BufferedWriter, FIle, FileInputStream, FileOutputStream, FileReader, FileWriter

당신이 PS에서 Scanner를 쓰면 안 되는 이유 (JAVA)