시작
백준 이 문제로부터 영감을 얻게 된 포스팅이다.
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 |