skip to content

Standard Streams & Redirection

System.in, out and err, and the setIn/setOut/setErr methods that redirect them — most usefully for capturing output in a test. Interviewers ask about it when discussing how to test code that prints.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What are the three standard streams in Java, what type is each, and what is each used for?

level: juniorimportance: must knowfreq 70%

answer

  1. in / out / err
  2. InputStream vs PrintStream
  3. descriptors 0 / 1 / 2
  4. err auto-flushes, out buffered
  5. out and err redirect independently

basics

~10 s

Java has three standard streams: System.in for reading input, System.out for normal output, and System.err for errors. System.in is an InputStream; System.out and System.err are PrintStreams.

solid answer

~40 s

Java exposes three public static fields on java.lang.System. System.in is an InputStream, the program's standard input, normally the keyboard or a piped file. System.out is a PrintStream for normal program output. System.err is also a PrintStream, meant for error messages and diagnostics. out and err are separate so they can be redirected independently: you can send normal output to a file while still seeing errors on screen. System.err is typically unbuffered (auto-flush) so error messages appear immediately even if the program crashes. All three are set up by the JVM at startup and connect to the OS-level file descriptors 0, 1 and 2.

code

java · 11 lines
java
public class Streams {
    public static void main(String[] args) throws Exception {
        System.out.println("normal output -> stdout (fd 1)");
        System.err.println("diagnostic     -> stderr (fd 2)");
        // System.in is a raw byte stream; wrap it to read text
        var reader = new java.io.BufferedReader(
                new java.io.InputStreamReader(System.in));
        String line = reader.readLine();
        System.out.println("you typed: " + line);
    }
}

go deeper

for a junior

Name the three streams and their direction (in=read, out/err=write) and that out/err show on the console by default.

for a middle

Add the exact Java types (InputStream vs PrintStream), the fd 0/1/2 mapping, and why out/err are separated for redirection.

for a senior

Explain the buffering/auto-flush difference and its crash-safety implication, plus how you wrap System.in (Scanner/BufferedReader) and choose a charset.

for a principal

Discuss process I/O design: descriptors as the contract between programs and shells/tools, why log frameworks default errors to stderr, and pitfalls of mixing application logging with stdout in pipelines.

## What a "stream" is A **stream** is an ordered, one-directional sequence of data. An **InputStream** is a source you read bytes *from*; an **OutputStream** is a sink you write bytes *to*. **PrintStream** is a convenient OutputStream subclass that adds text methods like `println`. Streams abstract over where the data really lives (keyboard, file, socket, another program). ## The three standard streams Every process launched from a shell inherits three pre-opened channels from the operating system, identified by small integers called **file descriptors**: - descriptor **0** = standard input ("stdin") - descriptor **1** = standard output ("stdout") - descriptor **2** = standard error ("stderr") The JVM wires these to three static fields on `java.lang.System`: | Field | Java type | Direction | Normal target | |---|---|---|---| | `System.in` | `InputStream` | read | keyboard / piped input | | `System.out` | `PrintStream` | write | console (normal output) | | `System.err` | `PrintStream` | write | console (errors/diagnostics) | ## Why out and err are separate Keeping normal output and error output on two descriptors lets the shell route them independently. `java App > out.txt` sends only stdout to the file; errors still appear on screen. `java App 2> err.txt` captures only errors. This separation is the whole point: a tool can consume a program's *data* (stdout) while a human still sees its *complaints* (stderr). ## Buffering difference `System.out` is buffered with auto-flush on newline; `System.err` auto-flushes on every write. That means if your program crashes, error messages already written to `System.err` are guaranteed on screen, whereas the last buffered `System.out` line might be lost. This is why you log errors to `System.err`, not `System.out`. ## Reading from System.in Because `System.in` is a raw byte `InputStream`, you usually wrap it for convenience, e.g. `new BufferedReader(new InputStreamReader(System.in))` for lines of text, or `new Scanner(System.in)` for tokens. The wrapping converts bytes to characters using a charset. ## First-principles takeaway The three streams are not magic: they are ordinary `InputStream`/`PrintStream` objects pointing at OS descriptors 0/1/2. Everything else (redirection, capturing in tests) is just swapping which object those fields point to.

  • Why might the last line printed to System.out be missing when a program crashes, but a System.err line is present?
    System.out is buffered (auto-flush only on newline / when the buffer fills), so a buffered line can be lost on an abrupt exit. System.err auto-flushes on every write, so its content reaches the console immediately.
  • Why is System.in an InputStream but System.out a PrintStream rather than just an OutputStream?
    Input is raw bytes you parse yourself, so the generic InputStream is enough. Output is mostly human-readable text, so PrintStream adds print/println/printf convenience and charset encoding on top of OutputStream.

Think of a worker at a counter: stdin is the in-tray they read requests from, stdout is the out-tray for finished work, stderr is a separate complaint slip they hand off immediately so it isn't buried in the out-tray.

saying these in an interview costs you the question

  • Saying System.out and System.err are the same stream or interchangeable
  • Claiming System.in is a PrintStream or a Reader (it is a byte InputStream)
  • Thinking System.err is for 'less important' output rather than errors/diagnostics
  • Assuming all three are always the console even after redirection

context

open as a page

System.in is a raw InputStream. How do you read a line or tokens of text from it correctly, and what must you get right?

level: juniorimportance: should knowfreq 50%

basics

~10 s

System.in gives raw bytes, so wrap it. Use new Scanner(System.in) for tokens/lines, or new BufferedReader(new InputStreamReader(System.in)) and call readLine() for whole lines. Choose a charset and don't close System.in if you still need it.

open as a page

How do you programmatically redirect System.out (or System.err) inside a running JVM, and how do you safely restore it?

level: middleimportance: should knowfreq 55%

basics

~10 s

Call System.setOut(new PrintStream(...)) with your own PrintStream (for example one wrapping a ByteArrayOutputStream or a file). Save the original first and restore it afterward with System.setOut(original).

open as a page

System.in, System.out and System.err are declared public static final. How can System.setIn/setOut/setErr reassign them, and what does that reveal about the JVM?

level: seniorimportance: nice to knowfreq 30%

basics

~10 s

The three fields are final, so normal Java code cannot reassign them. The setIn/setOut/setErr methods are native: the JVM is allowed to mutate these specific final fields internally, which ordinary bytecode is not.

open as a page

What problems arise from redirecting System.out/err/in to test or capture console I/O, and how would you design around them?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

Redirecting the standard streams changes global, process-wide state, so it is racy under parallel tests, leaks if not restored, and depends on charset/flushing. Better designs inject a PrintStream/Appendable or use a logging framework so you can capture output without touching globals.

open as a page