What are the three standard streams in Java, what type is each, and what is each used for?
answer
- in / out / err
- InputStream vs PrintStream
- descriptors 0 / 1 / 2
- err auto-flushes, out buffered
- out and err redirect independently
basics
~10 sJava 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 sJava 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 linespublic 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
Name the three streams and their direction (in=read, out/err=write) and that out/err show on the console by default.
Add the exact Java types (InputStream vs PrintStream), the fd 0/1/2 mapping, and why out/err are separated for redirection.
Explain the buffering/auto-flush difference and its crash-safety implication, plus how you wrap System.in (Scanner/BufferedReader) and choose a charset.
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