Java Input and Output

A complete guide to reading input and writing output in Java: the print family, formatted output with printf and String.format, the Scanner and BufferedReader classes, System.err, and the Console class.

System.out.println() and System.out.print()

System.out is a static field of type PrintStream that represents the standard output stream, typically the terminal or console. It provides several overloaded methods for writing output. The two you will use most in everyday Java are println() and print(). They differ in exactly one way: whether a newline is appended after the output.

println() vs. print()

Both accept any primitive type, char arrays, and objects (calling toString() on them). The sole difference is the newline.

  • System.out.println(value):Prints the value and then moves the cursor to the next line. Calling println() with no argument prints a blank line.
  • System.out.print(value):Prints the value and leaves the cursor at the same position on the same line. The next print statement continues from there.
  • Concatenation with +:"Answer: " + 42 produces the String "Answer: 42" before it reaches println(). The + operator converts the int to a String automatically in this context.

println() and print() in Action

Java

Demonstrating newline behaviour and multi-type output.

System.out.printf() and Formatted Output

printf() stands for "print formatted." Unlike println(), which simply converts a value to a String, printf() gives you precise control over alignment, width, decimal places, padding, and sign display. It takes a format string as its first argument, followed by the values to substitute into the placeholders it contains. It does not automatically append a newline: you must include %n (or \n) in the format string yourself when a new line is needed.

Core format specifiers

Each specifier begins with a percent sign (%) and ends with a conversion character.

  • %d :Decimal integer (int, long). Example: printf("%d", 42) prints 42.
  • %f :Floating-point number. Default: 6 decimal places. Example: printf("%.2f", 3.14159) prints 3.14.
  • %s :String (or any object via toString()). Example: printf("%s", "Java") prints Java.
  • %c :Single character. Example: printf("%c", 74) prints J.
  • %b :Boolean. Example: printf("%b", true) prints true.
  • %n :Platform-specific newline. On Windows it produces \r\n; on Unix it produces \n. Prefer %n over \n in format strings.
  • %x :Integer in hexadecimal. %X produces uppercase letters.
  • %o :Integer in octal.
  • %e :Scientific notation (floating-point). Example: printf("%e", 123456.789) prints 1.234568e+05.

Width, precision, and flags

Format specifiers accept optional modifiers between the % and the conversion character.

  • Width:%10d reserves 10 characters, right-aligned. %-10d is left-aligned.
  • Precision:%.3f prints exactly 3 decimal places. %10.2f pads to 10 characters with 2 decimal places.
  • Zero-padding:%05d pads with leading zeros: 42 becomes 00042.
  • Plus sign:%+d always shows the sign: +42 or -42.
  • Comma separator:%,d adds thousands separators: 1000000 becomes 1,000,000.

printf() Formatted Output

Java

Width, precision, padding, and alignment applied to a formatted table.

String.format()

String.format() uses the exact same format string syntax as printf(), but instead of printing immediately it returns the formatted result as a String. This makes it the right choice whenever you need to build a formatted string to store in a variable, pass to a logging framework, include in an exception message, or send over a network. Use printf() when you want to print immediately; use String.format() when you need the formatted text as a value.

printf() vs. String.format()

Same syntax, different purpose.

  • System.out.printf(fmt, args):Formats and prints in one call. Returns void.
  • String.format(fmt, args):Formats and returns a String. No printing happens.
  • Formatted.formatted(args):Java 15+ instance method on String: "Price: %.2f".formatted(9.99). Identical to String.format but avoids repeating the format string as a class method argument.

String.format() for Building Strings

Java

Formatting a label, an error message, and a receipt line, all as Strings rather than printing directly.

Scanner Class for Input

The Scanner class, found in the java.util package, is the standard beginner-friendly way to read input in Java. It can wrap any InputStream, including System.in (keyboard input), a File, or a String. It tokenises input by breaking it at whitespace by default, and provides methods to read tokens as specific types. You must always close a Scanner when you are done with it, or use a try-with-resources block to close it automatically.

Common Scanner methods

Each method reads the next token and converts it to the indicated type. If the input does not match the expected type, an InputMismatchException is thrown.

  • nextInt():Reads and returns the next token as an int.
  • nextLong():Reads and returns the next token as a long.
  • nextDouble():Reads and returns the next token as a double.
  • nextFloat():Reads and returns the next token as a float.
  • next():Reads and returns the next whitespace-delimited token as a String.
  • nextLine():Reads and returns the remainder of the current line, including spaces, as a String.
  • nextBoolean():Reads "true" or "false" (case-insensitive) and returns a boolean.
  • hasNext():Returns true if there is another token available. Useful for reading until end of input.

Reading Multiple Types with Scanner

Java

Reading an int, a double, and a String from System.in in a single session.

nextLine() vs. next()

The difference between nextLine() and next() is one of the most common sources of subtle bugs for Java beginners, especially when mixing numeric methods like nextInt() with nextLine() in the same program. Understanding exactly what each method consumes from the input stream will save you hours of debugging.

What each method reads

The difference is in where each method stops reading and what it leaves behind in the buffer.

  • next():Skips leading whitespace, then reads characters until the next whitespace character. It does not consume the whitespace delimiter. Input "Hello World" gives "Hello" on the first call; "World" on the second.
  • nextLine():Reads all characters up to and including the newline character (\n), but returns only the characters before the newline. The newline itself is consumed but not included in the result.

The nextInt() + nextLine() bug

This specific sequence trips up almost every beginner. It is worth understanding thoroughly.

  • When a user types 25 and presses Enter, the input buffer contains: 25\n
  • nextInt() reads 25 but stops before the \n. The \n is left in the buffer.
  • The subsequent nextLine() immediately reads that leftover \n and returns an empty String before the user has a chance to type anything.
  • Fix: call nextLine() once immediately after nextInt() to consume the leftover newline, then call nextLine() again for the actual input.

nextLine() vs. next() and the Newline Trap

Java

Demonstrates the leftover newline bug and how to fix it with a consuming nextLine() call.

BufferedReader for Input

BufferedReader is the preferred approach for reading text input in performance-sensitive or production code. While Scanner reads the input one token at a time and is relatively slow, BufferedReader reads a large chunk at a time into an internal buffer, then serves your reads from that buffer. This dramatically reduces the number of actual I/O operations and is the standard choice for competitive programming, reading large files, and high-throughput applications.

BufferedReader vs. Scanner

Both can read console input, but they serve different needs.

  • BufferedReader pros:Faster for large inputs, thread-safe, read() and readLine() are straightforward.
  • BufferedReader cons:Requires wrapping with InputStreamReader, does not parse types directly (you must call Integer.parseInt() yourself), and readLine() throws checked IOException.
  • Scanner pros:Parses int, double, etc. directly, simpler syntax for beginners.
  • Scanner cons:Slower due to regex-based tokenisation, not thread-safe, the nextLine() newline trap.

Setting up BufferedReader

Three classes are involved: System.in (the raw stream), InputStreamReader (bridges bytes to characters), and BufferedReader (adds buffering).

  • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  • String line = br.readLine(); reads one full line, returns null at end of input.
  • Integer.parseInt(br.readLine().trim()) to read an integer.
  • Always close BufferedReader in a finally block or use try-with-resources.

BufferedReader for Console Input

Java

Reading a name, an integer, and a double using BufferedReader with try-with-resources.

System.err for Error Output

Java provides two separate output streams: System.out for standard output and System.err for standard error. Both are PrintStream instances and support the same print(), println(), and printf() methods. The critical difference is not the API but the stream destination: the two streams can be redirected independently at the OS level, which is how production systems separate normal application logs from error logs.

Why System.err matters

The separation between stdout and stderr exists for a practical operational reason.

  • In a terminal: both streams appear mixed together, so you see no visible difference while developing.
  • In production: java MyApp > output.log 2> error.log redirects stdout to one file and stderr to another, cleanly separating normal output from diagnostic errors.
  • Logging frameworks (Log4j, SLF4J) write to stderr internally for error-level events. Understanding stderr helps you understand how those frameworks work.
  • System.err is not buffered by default, messages written to it appear immediately, which is deliberate: you want error output to show up even if the program crashes before flushing a buffer.

System.err vs. System.out

Java

Normal output goes to stdout; errors and diagnostics go to stderr.

Console Class

The Console class, available via System.console(), provides two capabilities that Scanner cannot match: reading a password without echoing the characters to the screen, and a built-in printf()-style method that writes directly to the console. There is an important limitation: IDEs like IntelliJ IDEA and VS Code do not attach a real system console to the JVM process, so System.console() returns null when run inside most IDEs. It works correctly when you run the program from a real terminal.

Console class methods

A small, focused API covering formatted output, line reading, and secure password input.

  • console.readLine():Reads a line of text from the console. Returns null at end of input.
  • console.readLine(fmt, args):Displays a formatted prompt, then reads a line.
  • console.readPassword():Reads input without echoing it. Returns a char[] rather than a String so you can zero it out after use, preventing the password from sitting in memory as a String.
  • console.printf(fmt, args):Writes formatted output to the console.
  • console.format(fmt, args):Same as printf(), returns the Console for chaining.

Why readPassword() returns char[] instead of String

This is a deliberate security decision worth understanding.

  • Strings in Java are immutable and interned: once created, the contents sit in memory until garbage collected, which can be an unpredictably long time.
  • A char[] can be explicitly zeroed (Arrays.fill(password, 0)) immediately after use, minimising the window during which the password exists in plaintext memory.
  • This only matters for security-sensitive applications, but it is the pattern established by every Java security API.

Console Class Usage

Java

Reading a line and a password via Console. Run this from a real terminal, not an IDE, for Console to be non-null.

Formatting with printf: Complete Reference

This section brings together all the printf formatting rules in one place as a practical reference. The full format specifier syntax is: %[flags][width][.precision]conversion. Each component is optional except the conversion character, and they must appear in that order. Knowing this structure lets you decode any format string you encounter and construct the output layout you need without trial and error.

Format specifier anatomy

Breaking down the full structure of a format specifier.

  • % :Required opening character. Marks the start of a format specifier.
  • Flags (optional):- (left-align), + (always show sign), 0 (zero-pad), , (thousands separator), space (space before positive numbers), ( (enclose negatives in parentheses).
  • Width (optional):Minimum total field width as a decimal integer. Output is padded to this width with spaces (or zeros if the 0 flag is set).
  • .precision (optional):For %f/%e: number of digits after the decimal point. For %s: maximum number of characters to print.
  • Conversion (required):d f s c b x o e n, the type of value to format.

Quick-reference table

The most useful combinations with their output.

  • %-20s : left-align String in a 20-character field
  • %20s : right-align String in a 20-character field
  • %d : integer with no formatting
  • %,d : integer with thousands separators
  • %05d : zero-padded integer, total width 5
  • %.2f : float with exactly 2 decimal places
  • %10.2f : float, right-aligned in 10-char field, 2 decimals
  • %-10.2f : float, left-aligned in 10-char field, 2 decimals
  • %,10.2f : float with thousands separator in 10-char field
  • %e : scientific notation, 6 decimal places by default
  • %.3e : scientific notation, 3 decimal places
  • %n : platform newline (prefer over \n in format strings)

printf Formatting Reference in Practice

Java

A comprehensive invoice report demonstrating alignment, precision, separators, and mixed types.

Quiz - Test Your Knowledge

Ten questions covering print methods, printf formatting, Scanner, nextLine vs. next, BufferedReader, System.err, and the Console class. Read each option carefully before selecting your answer.

Knowledge Check

1. What is the key difference between System.out.println() and System.out.print()?

2. Which format specifier does printf() use to print a floating-point number in Java?

3. What does Scanner.nextLine() return when called immediately after Scanner.nextInt()?

4. Which class must be imported to use Scanner in Java?

5. What is the difference between Scanner.next() and Scanner.nextLine()?

6. Which stream does System.err write to?

7. What does String.format("%05d", 42) produce?

8. BufferedReader is preferred over Scanner for reading large files primarily because:

9. Which format specifier in printf() outputs a platform-specific line separator?

10. What happens if you call System.console() inside an IDE like IntelliJ or VS Code?