When should you choose BufferedReader over Scanner for reading input, and why?
answer
- Scanner = convenience + typed parsing + locale; slower
- BufferedReader = speed via buffering; readLine only, you parse
- Large input / tight loop -> BufferedReader
- Hot loop idiom: BufferedReader + StringTokenizer
- Scanner not thread-safe; readLine is synchronized
basics
~20 sUse Scanner when you need easy token parsing of small input. Use BufferedReader when you need speed or to read large input, because it reads lines fast but does not parse types for you, so you split and convert the text yourself.
solid answer
~40 sScanner and BufferedReader solve different problems. Scanner offers convenient typed token parsing (nextInt, nextDouble) and is locale-aware, which is great for small, structured console input. But it is comparatively slow because each read involves regex matching, and it is not thread-safe. BufferedReader just buffers characters and gives you readLine(); it has no parsing, so you call split() and Integer.parseInt yourself, but it is significantly faster and a better fit for large files or performance-sensitive code such as competitive programming. A common high-throughput idiom pairs BufferedReader with StreamTokenizer or a manual StringTokenizer per line. Choose Scanner for ergonomics on small input, BufferedReader (often with explicit parsing) when input volume or latency matters. Both should be closed if they own a file resource; neither should close System.in if you need it later.
code
java · 12 linesimport java.io.*;
import java.util.StringTokenizer;
// Fast input idiom for large data
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine().trim());
long sum = 0;
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
sum += Long.parseLong(st.nextToken());
}
System.out.println(sum);go deeper
Knows both can read input and that Scanner is easier because it parses numbers, while BufferedReader returns whole lines as strings.
Can rewrite Scanner code with BufferedReader plus split/parseInt and knows BufferedReader is faster for big input but does no parsing.
Reasons about the regex/locale overhead of Scanner versus buffered reads, picks the right tool by input size and latency, and knows the BufferedReader+StringTokenizer hot-loop idiom and null-at-EOF handling.
Weighs maintainability versus throughput at scale, sets input-handling conventions, and recognizes when neither fits and a streaming/NIO or dedicated parser is warranted.
## Two tools, two priorities Both `Scanner` and `BufferedReader` read text input, but they optimize for different things: **Scanner for convenience, BufferedReader for speed.** ### Scanner recap `Scanner` breaks input into **tokens** using a regex delimiter and **parses types for you** (`nextInt`, `nextDouble`, `nextBoolean`). It is **locale-aware** for numbers. The cost: every token read runs regular-expression matching, which is relatively **slow**, and Scanner is **not thread-safe**. ### BufferedReader recap `BufferedReader` wraps another reader and keeps an in-memory **buffer**, so it reads big chunks from the source at once instead of one character at a time — this is what makes it fast. Its main method is **`readLine()`**, which returns one line as a `String` (or `null` at end of input). It does **no parsing**: if you want numbers, you split the line and convert yourself. ```java BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); // "10 20 30" String[] parts = line.split("\\s+"); // ["10","20","30"] int a = Integer.parseInt(parts[0]); // you parse explicitly ``` ### Terms - **Buffer**: a chunk of memory holding many characters read in one go, so the program makes far fewer (expensive) calls to the OS. Fewer round-trips = faster. - **`readLine()`**: returns the next line of text without the line terminator; returns `null` at end of stream. - **`split(regex)`**: a `String` method that breaks the line into an array on a delimiter. - **`Integer.parseInt` / `Double.parseDouble`**: convert a `String` to a number. ## Decision factors | Factor | Scanner | BufferedReader | |---|---|---| | Typed parsing built in | Yes (`nextInt`, ...) | No — you `parseInt` yourself | | Speed on large input | Slower (regex per token) | Much faster (buffered) | | Locale-aware numbers | Yes | No (you control parsing) | | Ease for small console apps | Excellent | More boilerplate | | Thread-safety | Not synchronized | `readLine` is synchronized | ## When to pick which - **Pick Scanner** for small, interactive, or quick-and-dirty parsing where the typed methods save you effort and input size is tiny. Ergonomics win. - **Pick BufferedReader** when: - input is **large** (megabytes, many lines) or in a **tight loop** (e.g., competitive programming) — Scanner's per-token regex cost becomes the bottleneck; - you want full control over parsing and locale-independence; - you need to read raw lines and process them yourself. ## High-throughput idiom For maximum speed, many programs combine BufferedReader with a per-line tokenizer: ```java BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int a = Integer.parseInt(st.nextToken()); int b = Integer.parseInt(st.nextToken()); ``` `StringTokenizer` splits a line cheaply (no regex), which is even faster than `String.split` for hot loops. `StreamTokenizer` is another fast option for number-heavy streams. ## Shared concerns - **Closing**: both implement `Closeable`. Close them when they own a file; do **not** close one wrapping `System.in` if you still need standard input later (closing cascades to the underlying stream, just like with Scanner). - **Correctness vs. speed**: Scanner's parsing is safer to write but slower; BufferedReader trades convenience for raw throughput and forces you to handle parsing and `null`-at-EOF explicitly. ## Bottom line Reach for **Scanner** when convenience matters and input is small; reach for **BufferedReader** (often with manual tokenizing) when **performance or input size** dominates. They are not rivals so much as different points on the convenience-versus-speed curve.
- Why is Scanner slower than BufferedReader?Scanner tokenizes using regular-expression matching on each read and is locale-aware, which adds overhead per token, whereas BufferedReader simply returns buffered lines with no parsing, so it does far less work per unit of input.
- Does BufferedReader parse numbers for you?No. readLine() returns a String only. You must split the line (e.g. split or StringTokenizer) and convert with Integer.parseInt/Double.parseDouble yourself.
Scanner is a vending machine that hands you exactly the snack you ask for but is slow; BufferedReader is a bulk warehouse that dumps whole pallets quickly and leaves you to unpack them.
saying these in an interview costs you the question
- Claiming BufferedReader parses ints/doubles like Scanner does
- Using Scanner in performance-critical loops and blaming the algorithm for timeouts
- Thinking BufferedReader is always better — it loses Scanner's convenience and locale parsing
- Forgetting readLine() returns null at end of input and dereferencing it