[GPT 질문] Scanner보다 BufferedReader가 좋아?
나의 말:
java에서 입력을 받을때 왜 Scanner보다 BufferedReader가 왜 더 좋아?
ChatGPT의 말:
좋은 질문이에요! Java에서 입력을 받을 때 Scanner보다 BufferedReader가 더 좋다고 평가되는 이유는 주로 성능과 유연성 때문입니다. 아래에 비교해서 정리해볼게요.
✅ BufferedReader vs Scanner: 차이점 비교
항목 | BufferedReader | Scanner |
성능 | 빠름 (버퍼 사용) | 느림 (내부에서 정규표현식 사용) |
기반 클래스 | Reader 기반 (주로 InputStreamReader) | Readable 기반 |
입력 단위 | 한 줄(readLine()), 문자 | 토큰 단위 (next(), nextInt() 등) |
파싱 기능 | 없음 (직접 파싱 필요) | 있음 (nextInt(), nextDouble() 등 내장) |
입력 예외 처리 | IOException 필수 처리 | NoSuchElementException, InputMismatchException 등 |
줄바꿈 처리 | 명시적으로 처리 | 자동 처리 가능 |
🔍 BufferedReader가 더 나은 상황
- 대량의 데이터를 빠르게 입력받을 때 (예: 알고리즘 문제 풀이)
- 성능이 중요한 경우 (예: 온라인 저지, 백준)
- 입력을 줄 단위로 받고, 직접 파싱이 가능한 경우
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine(); // 한 줄 입력
int number = Integer.parseInt(input); // 직접 파싱
🔍 Scanner가 더 편한 상황
- 입력이 많지 않거나 복잡하지 않을 때
- 간단한 입력으로 빠르게 테스트할 때
- 토큰 단위 입력 처리가 필요한 경우
Scanner sc = new Scanner(System.in);
int number = sc.nextInt(); // 자동으로 int로 파싱해줌
🧠 요약
- BufferedReader는 빠르지만 불편 (직접 파싱 필요)
- Scanner는 편하지만 느림 (정규표현식 사용 때문)
그래서 알고리즘 문제나 대량 입력이 필요할 땐 BufferedReader를 추천합니다!
나의 말:
근데 BufferedReader를 이용하고 StringTokenizer를 이용해서 또 분리하고 Parsing까지 하는데 Scanner보다 빨라?
ChatGPT의 말:
네, 맞습니다.
BufferedReader + StringTokenizer 조합이 Scanner보다 확실히 빠릅니다.
심지어 StringTokenizer 없이 split()을 써도 대부분의 경우 Scanner보다 빠릅니다.
왜 그럴까요? 이유는 다음과 같습니다:
🔍 Scanner가 느린 이유
- Scanner는 정규표현식(Regex) 기반으로 동작합니다.
- nextInt(), next() 같은 메서드는 내부적으로 패턴 매칭을 수행하므로 처리 속도가 느립니다.
- 또한 입력마다 버퍼를 체크하기 때문에 반복적으로 I/O 작업이 발생하면 더 느려집니다.
⚡ BufferedReader + StringTokenizer가 빠른 이유
- BufferedReader는 한 줄을 통째로 읽기 때문에 I/O를 최소화합니다.
- StringTokenizer는 단순히 구분자를 기준으로 빠르게 문자열을 자르기만 하기 때문에 매우 가볍습니다. (정규표현식 사용 안 함)
- Integer.parseInt()로 직접 파싱하면 오버헤드가 거의 없습니다.
📊 예시 비교
// 빠름
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
StringTokenizer st = new StringTokenizer(line);
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
// 느림
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
위와 같이 같은 작업을 해도 BufferedReader + StringTokenizer 조합이 훨씬 빠릅니다.
✅ 결론
- 알고리즘 문제, 대량 입력 처리 시는 BufferedReader + StringTokenizer를 쓰는 게 더 빠름
- Scanner는 간단한 프로그램이나 실습 용도에는 사용하기 편하지만, 성능은 떨어짐
나의 말:
근데 BufferedReader에서는 IOException을 고려해야되지?
ChatGPT의 말:
맞습니다. BufferedReader를 사용할 때는 반드시 IOException을 처리해야 합니다.
이는 BufferedReader의 readLine() 메서드가 checked exception인 IOException을 던지기 때문입니다.
🔧 처리 방법 2가지
1. throws로 예외를 위임
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine(); // 예외 발생 가능
System.out.println(line);
}
→ 간단한 테스트용 코드에 적합. 예외 처리를 생략하고 싶을 때 사용.
2. try-catch로 직접 처리
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
String line = br.readLine();
System.out.println(line);
} catch (IOException e) {
System.out.println("입력 중 오류 발생: " + e.getMessage());
}
}
→ 실무나 안정성이 중요한 코드에서 사용. 예외 상황에 대응 가능.
💡 참고: Scanner는?
Scanner는 IOException을 unchecked exception으로 감싸기 때문에 try-catch가 필수는 아닙니다.
이 점 때문에 초보자들이 편하게 느끼는 경우도 많죠.
✅ 정리
항목 | BufferedReader | Scanner |
예외 처리 | IOException 필수 (throws 또는 try-catch) | 생략 가능 (내부 처리됨) |
초보자 친화도 | 낮음 (예외 처리 필요) | 높음 (예외 처리 생략 가능) |
예외 처리가 번거롭긴 해도, 성능이 중요한 경우 BufferedReader + 예외 처리 코드는 감수할 만한 가치가 있습니다.
나의 말:
BufferedReader 쓸때 IOException 말고 더 신경쓸게 있어?
ChatGPT의 말:
아, 정확한 의도 파악했어요. BufferedReader를 사용할 때 IOException 외에 개발자가 특별히 더 신경 써야 할 요소들을 아래에 정리해볼게요. 꽤 중요한 포인트들이 있습니다.
✅ BufferedReader 사용 시 IOException 외에 신경 써야 할 요소
1. null 반환 처리
- br.readLine()은 더 이상 읽을 줄이 없으면 null을 반환합니다.
- 이걸 체크하지 않으면 NullPointerException이 발생할 수 있어요.
String line;
while ((line = br.readLine()) != null) {
// 반드시 null 체크 필요
}
2. 숫자, 문자 등 파싱 실패 (NumberFormatException 등)
- readLine()은 항상 String으로 반환하기 때문에, 형 변환 시 예외가 발생할 수 있어요.
- 예: Integer.parseInt(), Double.parseDouble() 등
try {
int num = Integer.parseInt(br.readLine());
} catch (NumberFormatException e) {
System.out.println("잘못된 숫자 형식입니다.");
}
3. 버퍼 비움/flush 불필요하나 close()는 명시적 호출 필요
- BufferedReader는 출력 스트림이 아니라 flush()는 의미 없지만, 사용이 끝나면 반드시 close() 호출이 필요해요 (특히 파일/네트워크 기반이면 자원 누수 발생 가능)
br.close(); // System.in 기반이라면 생략 가능하지만, 명시적으로 해두는 게 좋음
4. 읽은 문자열의 앞뒤 공백 주의
- 사용자가 입력한 값에 공백이 포함될 수 있으므로 .trim()을 사용하는 것이 안전합니다.
String input = br.readLine().trim();
5. 한 줄 입력에 여러 값이 있는 경우 직접 파싱 필요
- Scanner처럼 nextInt() 등이 없으므로, 한 줄에 여러 값이 있을 경우 split() 또는 StringTokenizer로 직접 나누고 파싱해야 해요.
String[] parts = br.readLine().split(" ");
int a = Integer.parseInt(parts[0]);
int b = Integer.parseInt(parts[1]);
또는:
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
6. 입력 인코딩 문제 (특히 파일/네트워크 입력 시)
- 시스템 기본 인코딩과 실제 인코딩이 다를 수 있음 (예: UTF-8 vs EUC-KR)
- InputStreamReader에 인코딩을 명시하는 것이 바람직합니다.
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in, StandardCharsets.UTF_8));
🧠 핵심 체크리스트 요약
항목 | 설명 |
null 체크 | EOF 시 readLine()이 null 반환 |
형 변환 실패 | parseInt(), parseDouble() → NumberFormatException 가능 |
공백 제거 | 입력 앞뒤 공백 .trim() 처리 |
여러 값 파싱 | split() 또는 StringTokenizer 사용 필요 |
자원 정리 | close() 명시적으로 호출 |
인코딩 명시 | 파일/외부 입력 시 인코딩 오류 방지 |
추가 자료:
https://juno-juno.tistory.com/99
Scanner와 BufferedReader / BufferedWriter의 차이점과 사용법
이때까지 귀찮아서 Scanner만 항상 사용했는데, 이제야 정리를 해보고, 오늘 부로 절대 Scanner를 사용하는 과거로 돌아가지 않을 것이다. 1. Scanner Scanner는 띄어쓰기와 개행문자를 경계로 값을 인식
juno-juno.tistory.com
https://itbeginner2020.tistory.com/27
BufferedReader의 readLine() 은 왜 throws Exception 해주어야할까?
위와같이 main 에 throws Exception 해주지 않거나 try-catch 로 예외처리 하지 않으면 readLine() 메서드에 에러가 나는 이유가 갑자기 궁금해져 집요하게 파보았다. 사실 이런건 왜 발생하는가 보다 발생
itbeginner2020.tistory.com
https://cheese10yun.github.io/checked-exception/
Checked Exception을 대하는 자세
Checked Exception을 처리하는 전략과 그것에 유의해야 할 점들에 대해서 포스팅을 진행해보겠습니다. 자바에서는 대표적으로 Checked Exception 과 Unchecked Exception이 있습니다. 먼저 이 둘의 차이를 살펴
cheese10yun.github.io
https://jamesdreaming.tistory.com/126
[ 자바 코딩 ] NumberFormatException 원인과 해결방법
안녕하세요. 제임스 입니다. 이번에는 개발 중 종종 발생하는 오류중 하나인 NumbreFormatException 에 대해 정리 해보겠습니다. NumbreFormatException 은 왜 발생 하는 것일 까요? 단어를 잘 보시면 이유를
jamesdreaming.tistory.com