Java Module 27 – Java for DSA, placements and online assessments
Java fast I/O: large inputs and outputs
Read a million numbers in Java without the cost of a Scanner, print large outputs with one flush, and time your input and output the way a judge does.
What you will learn
- Read 10^6 numbers quickly with a BufferedReader or a byte reader
- Write large outputs through a PrintWriter or StringBuilder with a single flush
- Measure input and output cost on a judge-sized test instead of guessing
- Use one flush per question in interactive problems so that the judge never waits
Before you start
What you’ll learn · Before you start
What you will learn
- Read 10^6 numbers quickly with a BufferedReader or a byte reader
- Write large outputs through a PrintWriter or StringBuilder with a single flush
- Measure input and output cost on a judge-sized test instead of guessing
- Use one flush per question in interactive problems so that the judge never waits
Before you start
On this page
Fast I/O in Java comes down to two habits for large tests. Read the input through a BufferedReader cut into
tokens by a StringTokenizer, or through a small reader of your own that turns bytes into numbers, instead of a
Scanner. Send the output through one PrintWriter or StringBuilder that is flushed once at the end, instead of
calling System.out.println for every line, because System.out hands each line to the operating system the moment
you print it. Interactive problems are the exception to the second habit: there you flush after every question, or
the judge never sees it. With a few thousand numbers any of these choices is fast enough; from about 10^5 numbers on,
the difference starts to show against a time limit of one or two seconds.
Where the time goes
A program spends its input and output time in four places: decoding bytes into text, cutting the text into tokens, turning tokens into numbers, and handing finished text to the operating system. The usual readers and writers differ in how much of that work they do per number:
Scannerchecks every token against regular expressions before converting it, which makes it the slowest of the readers.BufferedReaderwithStringTokenizerreads whole lines, makes aStringof every token and converts it withInteger.parseInt.StreamTokenizerrecognises numbers by itself, with noStringper token, but stores every number as adouble.- A byte reader reads blocks of bytes and builds each number from its digits, with no
Stringand nodouble. System.out.printlnpasses each line to the operating system at once, so a million lines make a million separate writes.PrintWriterandStringBuildercollect the text in memory and write it out in large blocks, the last one at the flush.
Where the input and output time goes
Text description of the diagram
The diagram runs from top to bottom.
- A test file arrives as bytes on standard input.
- A box labelled "Reading: bytes to numbers" holds four readers, one above the other: Scanner, which checks every token against regular expressions; BufferedReader with StringTokenizer, which makes a String for every token and then converts it with parseInt; StreamTokenizer, which needs no String but stores every number as a double; and a byte reader, which turns the digits straight into an int.
- The numbers go to your algorithm.
- Its answers go to a box labelled "Writing: text to the operating system", which holds two writers: System.out.println, which makes one write for every line, and PrintWriter or StringBuilder, which make one write per block, the last one at the flush.
- The writes form the output file that the judge reads.
The writers make the largest difference, so here it is measured. WriteBench.java prints the same million lines
in one of four ways and reports, on standard error, the CPU time of the whole JVM and the time on the clock:
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
// Prints n lines, the numbers 0 to n-1 times 7, in one of four ways, and reports the cost on standard error,
// so that standard output can go to a file. Usage: java WriteBench.java println|writer|builder|printf n > out.txt
public class WriteBench {
public static void main(String[] args) {
String how = args[0];
int n = Integer.parseInt(args[1]);
var os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
long cpuStart = os.getProcessCpuTime();
long start = System.nanoTime();
switch (how) {
case "println" -> {
for (int i = 0; i < n; i++) System.out.println(i * 7L);
}
case "writer" -> {
PrintWriter out = new PrintWriter(System.out);
for (int i = 0; i < n; i++) out.println(i * 7L);
out.flush();
}
case "builder" -> {
StringBuilder text = new StringBuilder();
for (int i = 0; i < n; i++) text.append(i * 7L).append('\n');
System.out.print(text);
System.out.flush();
}
case "printf" -> {
PrintWriter out = new PrintWriter(System.out);
for (int i = 0; i < n; i++) out.printf("%d%n", i * 7L);
out.flush();
}
default -> throw new IllegalArgumentException("unknown writer: " + how);
}
long wallMs = (System.nanoTime() - start) / 1_000_000;
long cpuMs = (os.getProcessCpuTime() - cpuStart) / 1_000_000;
System.err.println(how + ": " + n + " lines, CPU " + cpuMs + " ms, wall " + wallMs + " ms");
}
} from session import run
# A million lines printed twice, once with System.out.println and once through a PrintWriter flushed at the end,
# each into its own file; then the two files are compared byte by byte.
run("""
javac -d classes WriteBench.java
java -cp classes WriteBench println 1000000 > println.txt
java -cp classes WriteBench writer 1000000 > writer.txt
cmp println.txt writer.txt && echo "the two files are identical"
""") Output
# JDK in use: openjdk version "25.0.4.1" LTS $ javac -d classes WriteBench.java $ java -cp classes WriteBench println 1000000 > println.txt println: 1000000 lines, CPU 4519 ms, wall 10454 ms $ java -cp classes WriteBench writer 1000000 > writer.txt writer: 1000000 lines, CPU 170 ms, wall 132 ms $ cmp println.txt writer.txt && echo "the two files are identical" the two files are identical
This output changes from run to run: The times depend on the computer and on what else it was doing; the two files are identical in every run.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 println_session.py
The two files are identical, byte for byte, yet System.out.println needed more than 20 times the CPU time of the
PrintWriter: about 4 to 5 seconds against under a fifth of a second on this track’s build machine, an Apple M5 Pro.
With a one-second limit, the same algorithm would be accepted with the second program and fail with the first.
Four readers on one million numbers, measured Pro: opens with a Pro, Premium or Ultimate pass
In this part:
- The byte reader, and what it does not check
- Four writers on one million lines, measured
- Lost output: four failure drills
- Measuring like a judge
- Exercise: answer a million range-sum questions in time
- Check yourself
- Interview questions
- A problem allows 1 second, gives 10^6 numbers as input and needs 10^6 lines of output, and your Java solution's algorithm is O(n log n). Estimate where the second goes, part by part, and say what you would measure first if the submission gets time limit exceeded.
- Your binary search for an interactive problem is correct, but the judge reports an idleness limit on the first test. You used your usual fast template, with one PrintWriter flushed at the end of main. Explain what happened, and how you write interactive input and output in Java.
- A teammate's contest template reads every number with a hand-written byte reader: it skips anything that is not a digit or a minus sign, builds the digits into a positive int and negates it after a minus. Review it: what could it get wrong, what does it accept silently, and when is it worth using?
- Key takeaways
10 runnable examples (FirstBroken.java, HaltDemo.java, Java, LostOutput.java, Numbers.java, Python, Ranges.java: the exercise, ReadBench.java, check_ranges.py: the sample tests, judge.py) · 3 interview answers · about 23 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
References
- Java SE 25 API: java.io.BufferedReader (Oracle)
- Java SE 25 API: java.util.StringTokenizer (Oracle)
- Java SE 25 API: java.io.StreamTokenizer (Oracle)
- Java SE 25 API: java.util.Scanner (Oracle)
- Java SE 25 API: java.io.InputStream (read into a byte array) (Oracle)
- Java SE 25 API: java.io.PrintWriter (Oracle)
- Java SE 25 API: java.io.PrintStream (automatic flushing) (Oracle)
- Java SE 25 API: com.sun.management.OperatingSystemMXBean (getProcessCpuTime) (Oracle)
- AtCoder Rules (how execution time is measured) (AtCoder)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress