Scanner VS BufferedReader

Neo-Renaissance·2025년 8월 4일

Scanner는 띄어쓰기와 줄바꿈문자를 경계로 하여 입력 값을 인식한다. 그렇기 때문에 따로 가공할 필요가 없어 편리하다. 하지만 다음에 살펴볼 BufferedReader은 입력 받은 데이터가 String으로 고정되기 때문에 입력받은 데이터를 원하는 타입으로 가공하는 작업이 필요하다.

Scanner는 지원해주는 메소드가 많고, 사용하기 쉽기 때문에 많이 사용하지만, 버퍼 사이즈가 1024 char이기 때문에 많은 입력을 필요로 할 경우에는 성능상 좋지 못한 결과를 불러온다.


BufferedReader

Scanner와 달리 BufferedReader는 줄 바꿈 문자만 경계로 인식하여 입력받는 과정이 끝나게되고 그줄의 내용을 공백 포함 모두 그대로 읽어오는 방식으로 입력받은 데이터가 String으로 고정된다. 그렇기 때문에 따로 데이터를 가공해야하는 경우가 많다. 하지만 Scanner보다 속도가 빠르다!

또한 BufferedReader는 동기화 되기 때문에 멀티 쓰레드 환경에서 안전하고, Scanner는 동기화가 되지 않기 때문에 멀티 쓰레드 환경에서 안전하지 않다.

입력받는 과정에 대한 예시

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        String line1 = br.readLine(); // "Hello World"
        String line2 = br.readLine(); // "This is a test"
        
        System.out.println("First line: " + line1); // 출력: "Hello World"
        System.out.println("Second line: " + line2); // 출력: "This is a test"
    }
}

BufferedReader 사용법

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 선언
String s = br.readLine();
int i = Integer.parseInt(br.readLine());

입력은 readLine();이라는 메소드를 사용한다. String으로 리턴 값이 고정되어 있기 때문에, 다른 타입으로 입력을 받고자 한다면 반드시 형변환이 필요하다. 그리고, 예외처리를 반드시 필요로 한다. readLine()시 마다 try/catch문으로 감싸주어도 되고, throws IOException 을 통한 예외처리를 해도 된다. (대부분의 경우에 후자를 사용한다.)

데이터 가공

BufferedReader를 통해 읽어온 데이터는 개행문자 단위(Line 단위)로 나누어진다. 만약 이를 공백 단위로 데이터를 가공하고자 하면 따로 작업을 해주어야 한다. 이때 사용하는 것이 StringTokenizerString.split()함수이다.

💡 만약에 입력 값이 한 줄씩 들어온다면 입력값을 받을 때마다 직전에 st = new StringTokenizer(br.readLine()); 를 반복해서 입력해줘야한다.

// StringTokenizer 
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());

// String.split() 함수
String arr[] = s.split(" "); // 배열에 공백단위로 끊어서 저장

BufferedWriter

많은 양의 출력을 할 때는, 입력과 동일하게 버퍼를 사용하는 것이 좋다.

BufferedWriter 사용법

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); // 선언
String str = "abcdef"; // 출력할 문자열
bw.write(s); // 출력
bw.newLine(); // 줄바꿈
bw.flush(); // 남아있는 데이터 모두 출력
bw.close();

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

int 정수형을 출력하고 싶은 경우에는 BufferedWriter 자체도 String을 기본형으로 가지기 때문에 형변환을 통해서 출력해줘야한다. bw.write(String.valueOf(정수)); 와 같이 사용한다.

예시

입력: 첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 위치 i와 j가 주어진다.

출력:

각 줄마다 배열의 위치와 위치에 존재하는 값들의 합을 출력한다.

input:

5 3

5 4 3 2 1

1 3

2 4

5 5
import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args)throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
				// n과 m 값을 공백으로 구분하여 입력받음
				int arr[] = new int[n];
        int sum[] = new int[m];

        st = new StringTokenizer(br.readLine());
        // 다음 줄에서 배열 arr에 저장할 입력 값을 공백 기준으로 처리
        for (int i = 0; i < n; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }

        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine());
            // 매 줄마다 공백을 기준으로 입력을 처리하기 위해 재선언
            int index = Integer.parseInt(st.nextToken()) - 1;
            int index2 = Integer.parseInt(st.nextToken()) - 1;
            sum[i] = arr[index] + arr[index2];
        }

        for (int i = 0; i < m; i++) {
            bw.write(String.valueOf(sum[i]));
            bw.newLine();
        }
        
        bw.flush();
        bw.close();
    }
}
profile
if (실패) { 다시 도전; } else { 성공; }

0개의 댓글