[Java] 빠른 입력과 출력: BufferedReader와 BufferedWriter + Buffer (with 백준15552)

2025. 2. 12. 15:31·😺 언어/☕Java

시작

백준 이 문제로부터 영감을 얻게 된 포스팅이다.

 

https://www.acmicpc.net/problem/15552
본격적으로 for문 문제를 풀기 전에 주의해야 할 점이 있다. 입출력 방식이 느리면 여러 줄을 입력받거나 출력할 때 시간초과가 날 수 있다는 점이다.
Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다.

 

Buffer를 써본 적 없는 건 아니지만 확실히 기존에는 대부분 System.out.print와 Scanner로 처리하려고 했다. 정리해보면 좋을 것 같다.

 

Buffer?

일단, System.in과 System.out.print보다 BufferedReader, BufferedWriter를 쓰는 게 효율적이라고 한다.
버퍼가 뭐길래 효율적일까?

Buffer

버퍼란 데이터를 임시로 저장하는 메모리 공간이다. 버퍼를 사용하면 데이터 입출력 작업을 여러 번 요청하는 대신 한 번에 대량의 데이터를 처리할 수 있다.

BufferedReader

참고: Oracle 공식 문서

Read 요청을 기준으로 조금 더 자세히 들어가보자.

파일 속 내용과 같은 대량의 데이터를 한 번에 읽고, 이를 버퍼에 저장하여 사용자가 요청할 때마다 제공하면 디스크 접근 횟수가 줄어들기 때문에 Scanner보다 효율적이라고 할 수 있는 것이다.

Scanner에 버퍼가 없는 것은 아니지만 버퍼 크기가 BufferedReader보다 작고, nextInt()와 같이 형 변환 기능을 제공하는 경우가 있어, 단순히 텍스트 데이터를 읽기만 하고 변환하지 않는 BufferedReader보다는 느리다.

그러나 읽어야 하는 데이터가 적은 경우, 사용자가 콘솔에 입력하거나 데이터를 int형 등 다른 형으로 변환해야 하는 경우에는 BufferedReader보다 Scanner가 유용할 수 있다.

 

공식 문서에 따르면 일단 다음 패키지를 import 해야 한다. 하지만 어차피 이것 저것 추가하게 될테니 *로 하는 것이 낫겠다.

import java.io.BufferedReader;
///
import java.io.*;

콘솔 입력을 입력받는 경우 System.in을 이용한다. 이때는 java.io.InputStreamReader 패키지가 필요하다.

  • BufferedReader(): 버퍼를 입력해 입력
  • InputStreamReader(System.in): 사용자 입력 스트림
  • FileReader({filename}): 파일 입력 스트림
  • readLine(): 버퍼에서 한 줄씩 읽기
  • read(): 버퍼에서 한 글자씩 읽기
//선언
BufferedReader br =  new BufferedReader(new InputStreamReader(System.in));	
// 버퍼에서 한 줄씩 읽기
String str = br.readLine();

 

IOException을 고려한 예외처리까지 하면 다음과 같은 코드를 쓸 수 있다. 실제 실행 시에는 반드시 예외처리를 해야 한다.

import java.io.*;

public class Main {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

파일 데이터를 읽어보자. java.io.FileReader 패키지가 필요하다.

 

import java.io.*;

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

읽을 때 무조건 문자열 String으로 읽기 때문에 다른 형으로 변환하고 싶다면 형변환을 이용해야 한다. 예를 들어 정수형으로 바꾸고자 한다면 다음과 같이 할 수 있을 것이다.

int a = Integer.parseInt(br.readLine());

 

BufferedWriter

참고: Oracle 공식 문서

버퍼를 사용해 데이터를 모았다가 한 번에 출력한다. I/O 작업이 System.out.print보다 최소화되었으므로 빠르다.

마찬가지로 import한다.

  • BufferedWriter(): 버퍼를 이용해 출력
  • OutputStreamWriter(System.out): 콘솔 출력 스트림
  • FileWriter({filename}): 파일 출력 스트림
  • write(): 버퍼에 쓰기
  • newLine(): 버퍼에서 줄 바꾸기. write 시 "\n"을 함께 써도 된다.
  • flash(): 버퍼에 있는 내용을 모두 출력하기
  • close(): BufferedWriter를 종료하기
import java.io.*;

public class Main {
	public static void main(String[] args) {
    	try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            for (int i = 1; i <= 1000; i++) {
                bw.write("This is line " + i);
                bw.newLine(); // 줄바꿈
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

백준 문제 해결

그렇다면 맨 위에서 언급한 '빠른 A+B' 문제는 아래 코드로 풀 수 있다.

import java.io.*;

public class Main{
    public static void main(String[] args){
        try{
            // BufferedReader, Writer 선언
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

            // 테스트 케이스의 개수 입력
            int t = Integer.parseInt(br.readLine());

            // 모든 테스트케이스에 대하여 반복
            for(int i = 0; i < t; i++){
                String str=br.readLine();
                // 띄어쓰기를 기준으로 A와 B 분리
                int idx = str.indexOf(' ');
                int a = Integer.parseInt(str.substring(0,idx));
                int b = Integer.parseInt(str.substring(1+idx,str.length()));
                // 연산과 저장
                bw.write((a+b)+""); // int를 문자열로 바꾸어 저장
                bw.newLine();
            }
            
            // 한 번에 출력
            bw.flush();
            bw.close();
            
        } catch(IOException e){
            e.printStackTrace();
        }

    }
}
반응형

'😺 언어 > ☕Java' 카테고리의 다른 글

[JAVA] 투 포인터 (백준 2018번, 백준 1940번)  (3) 2025.05.18
[JAVA] 구간 합 구하기 (백준 11659번, 백준 2042번)  (1) 2025.05.17
[JAVA] 배열과 리스트: 숫자의 합 구하기(백준 11720)  (3) 2025.05.14
[자료구조][Java] HashSet 중복 제거 동작 원리: HashSet은 어떻게 중복을 확인하나요?  (0) 2025.02.13
[Java] 스트림 Stream 개념과 Stream API 총정리  (2) 2025.02.13
'😺 언어/☕Java' 카테고리의 다른 글
  • [JAVA] 구간 합 구하기 (백준 11659번, 백준 2042번)
  • [JAVA] 배열과 리스트: 숫자의 합 구하기(백준 11720)
  • [자료구조][Java] HashSet 중복 제거 동작 원리: HashSet은 어떻게 중복을 확인하나요?
  • [Java] 스트림 Stream 개념과 Stream API 총정리
소영 🍀
소영 🍀
Hello World ✨
  • 소영 🍀
    Soyoung's Dev Lab
    소영 🍀
  • 전체
    오늘
    어제
  • 글쓰기 관리
    • 분류 전체보기 (42)
      • 📢 게시판 (0)
      • 📚 자료구조 & 알고리즘 (1)
      • 🌿Spring (15)
      • 😺 언어 (7)
        • ☕Java (7)
      • 📊 데이터베이스 (3)
      • 📤 배포 (4)
      • 🔎 객체지향프로그래밍 (1)
      • ⚙️ 기타 개발 자료 (9)
      • 🖥️ 프로젝트 (0)
      • 👩‍💻 활동 & 후기 (0)
      • 🍵 이야기 (2)
  • 블로그 메뉴

    • 태그
  • 링크

    • github
    • velog
  • 공지사항

  • 인기 글

  • 태그

    객체지향프로그래밍
    서버
    코드잇 스프린트
    알고리즘
    개발
    GIT
    배포
    docker
    코딩테스트
    Spring Security
    Java
    자료구조
    데이터베이스
    Spring
    위클리 페이퍼
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
소영 🍀
[Java] 빠른 입력과 출력: BufferedReader와 BufferedWriter + Buffer (with 백준15552)
상단으로

티스토리툴바