Java Standard Streams: System.in, System.out and System.err - Quiz

Total: 5 questions

1. 

What are the standard streams in Java: System.in, System.out and System.err?

They are three ready-made streams that the JVM creates when the program starts and stores in the public static final fields of the java.lang.System class. The java.lang package is imported automatically, so the streams are available without import and without creating any objects.

  • System.in is standard input, of type InputStream (a byte stream), OS descriptor 0, the keyboard by default.
  • System.out is standard output, of type PrintStream, descriptor 1, the terminal screen by default.
  • System.err is the standard error stream, also a PrintStream, descriptor 2, the terminal screen by default.

The link to the terminal is not fixed: the shell can redirect any of the streams to a file (<, >, 2>), and the program can replace them with System.setIn(), setOut() and setErr().

2. 

How does System.err differ from System.out, and when should you use it?

Both fields are PrintStream objects with the same methods (print(), println(), printf()). The difference is the OS channel: System.out writes to standard output (descriptor 1), System.err to the standard error stream (descriptor 2).

  • Errors can be separated from useful output: with java App > out.txt normal output goes to the file, while System.err messages stay on the screen; 2> err.txt sends errors to a separate file, and > all.txt 2>&1 puts both streams into one file.
  • The no-argument e.printStackTrace() writes to System.err, which is why stack traces are shown in red in an IDE.
  • Because these are two independent channels, out and err lines can come out in the wrong order in an IDE console; if the order matters, write to one stream.

Real applications use a logger (java.util.logging, SLF4J with Logback) instead of printing to System.err directly.

3. 

Why does System.in.read() return 53 when the user types 5, and how do you read a number from the console correctly?

System.in is a byte stream (InputStream). The method read() returns one byte as an int from 0 to 255, or -1 at the end of input. 53 is the code of the character '5', and the next call returns 10 (the line break from Enter; on Windows 13 comes first). The call blocks the program until the user presses Enter.

To read a number, read a line and parse it:

BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(console.readLine().trim());
  • InputStreamReader turns bytes into characters, BufferedReader adds readLine().
  • Non-numeric input throws NumberFormatException; at the end of input (Ctrl+D on Linux/macOS, Ctrl+Z and Enter on Windows) readLine() returns null.
  • Do not close the wrapper around System.in: closing it also closes System.in itself, and it cannot be reopened.
4. 

How do you redirect the standard streams from inside a program with System.setIn(), System.setOut() and System.setErr()?

The static methods System.setIn(InputStream), setOut(PrintStream) and setErr(PrintStream) replace the standard streams: after the call, all code that writes to System.out or reads from System.in works with the new stream, such as a file or an in-memory buffer.

  • setIn(new ByteArrayInputStream("42\n".getBytes())) feeds prepared input to code in a test.
  • setOut(new PrintStream(buffer, true)) with a ByteArrayOutputStream captures the output of a method that prints its result instead of returning it.
  • setErr(...) collects error messages and stack traces in a log file.

The fields in, out and err are declared final, so System.out = ... does not compile; the setXxx() methods change them through native JVM code. Save the original stream and restore it in a finally block; otherwise all later output of the program and of other tests goes into a foreign stream.

5. 

Why does System.out.println() never throw IOException, and why can it slow a program down in big loops?

The PrintStream methods (print(), println(), printf()) do not throw IOException: a write error only sets an internal flag. The only way to learn about a failure is to call checkError(), which flushes the buffer and returns true if an error occurred. That is why, for example, after System.out.close() all further output silently disappears.

The JVM creates System.out with automatic flushing (autoflush): text appears in the console right after println(), with no flush() call. The flip side is that every call goes to the OS, and the PrintStream methods are also synchronized, so a million println() calls can take seconds. For large output, collect the text in a StringBuilder and print it once, or write through new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))) with a single flush() at the end.

Page 1 of 1