foreach-ui logo
codeLanguages
account_treeDSA

Quick Actions

quizlock Random Quiz
trending_uplock Progress
  • 1
  • 2
  • 3
  • 4
  • quiz
Java
  • Understand Java's standard streams: System.in, System.out, System.err
  • Learn basic console input and output operations
  • Master proper resource management for I/O operations

Standard Input/Output Streams in Java

Every Java program needs to talk to the outside world. You print messages to show what's happening. You read input from users. You report errors when things go wrong. Java gives you three built-in streams to handle all of this.

Think of streams as pipes connecting your program to the console. Java sets up three of them automatically:

  • System.out writes your normal output to the console
  • System.err writes error messages (often shown in a different color)
  • System.in reads input from the keyboard

Let's see how each one works.

System.out - Your Program's Voice

When your program needs to say something, System.out is what you use. It's a PrintStream that writes to the console.

public class BasicOutput {
    public static void main(String[] args) {
        // Simple output
        System.out.println("Hello, World!");
        
        // Output without newline
        System.out.print("Hello");
        System.out.print(" World");
        System.out.println("!");  // Output: Hello World!
        
        // Formatted output
        System.out.printf("Name: %s, Age: %d%n", "Alice", 25);
    }
}

System.err - For When Things Go Wrong

Errors and warnings don't belong mixed with your normal output. That's why Java gives you System.err—a separate stream for problems.

public class ErrorOutput {
    public static void main(String[] args) {
        System.out.println("This is normal output");
        System.err.println("This is an error message");
        
        // Error output may be displayed differently (in red) in some IDEs
        System.err.println("Warning: Something went wrong!");
    }
}

System.in - Reading User Input

Getting input from the keyboard is trickier. System.in exists, but it's not as straightforward as System.out. It reads raw bytes, which makes working with text awkward.

import java.io.IOException;

public class BasicInput {
    public static void main(String[] args) throws IOException {
        System.out.print("Enter a character: ");
        int input = System.in.read();  // Reads one byte
        System.out.println("You entered: " + (char) input);
    }
}

Why System.in Is Problematic

Using System.in directly feels like you're working too close to the metal. It gives you bytes when you want characters. It doesn't buffer, so every read hits the system. And forget about reading numbers—you'd have to parse them yourself.

Here's what happens when you try to read an age directly:

public class ProblematicInput {
    public static void main(String[] args) throws IOException {
        System.out.print("Enter your age: ");
        int age = System.in.read();  // This reads a single byte/character!
        System.out.println("Age: " + age);  // Wrong result
    }
}

The Better Way: Wrap It

You want to read text, not bytes. Wrap System.in with BufferedReader and InputStreamReader. Now you can read whole lines at once, and the buffering makes it efficient.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class BufferedInput {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(System.in));
        
        System.out.print("Enter your name: ");
        String name = reader.readLine();
        
        System.out.println("Hello, " + name + "!");
        
        reader.close();  // Always close resources
    }
}

PrintWriter for Fancy Output

If you need more control over output, PrintWriter gives you extra options beyond what System.out offers.

import java.io.PrintWriter;

public class PrintWriterExample {
    public static void main(String[] args) {
        PrintWriter writer = new PrintWriter(System.out, true);
        
        writer.println("This is a line");
        writer.print("This is ");
        writer.print("concatenated ");
        writer.println("output");
        
        writer.printf("Formatted: %s is %d years old%n", "Alice", 25);
        
        writer.close();
    }
}

Redirecting Streams

Sometimes you want your output going to a file instead of the console. Java lets you redirect the streams wherever you need them.

import java.io.FileOutputStream;
import java.io.PrintStream;

public class StreamRedirection {
    public static void main(String[] args) throws Exception {
        // Redirect System.out to a file
        PrintStream fileOut = new PrintStream(new FileOutputStream("output.txt"));
        System.setOut(fileOut);
        
        System.out.println("This goes to file instead of console");
        
        fileOut.close();
    }
}

Don't Forget to Close Your Resources

Opening a stream creates a connection to the system. When you're done, close it. Leaving streams open wastes system resources.

The old way requires careful exception handling:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ResourceManagement {
    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("Enter input: ");
            String input = reader.readLine();
            System.out.println("You entered: " + input);
        } catch (IOException e) {
            System.err.println("Error reading input: " + e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    System.err.println("Error closing reader: " + e.getMessage());
                }
            }
        }
    }
}

The better way uses try-with-resources (Java 7+), which closes automatically:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class TryWithResources {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(System.in))) {
            
            System.out.print("Enter input: ");
            String input = reader.readLine();
            System.out.println("You entered: " + input);
            
        } catch (IOException e) {
            System.err.println("Error reading input: " + e.getMessage());
        }
        // reader is automatically closed
    }
}

Keep Errors Separate

When debugging or logging, you want errors distinct from normal output. Use System.err for problems, System.out for results. Many tools can filter them separately.

public class OutputSeparation {
    public static void main(String[] args) {
        System.out.println("This is normal program output");
        System.err.println("This is an error or warning message");
        
        // In command line, these can be redirected separately:
        // java OutputSeparation > output.txt 2> errors.txt
    }
}

Putting It Together

Building a simple console app? Use BufferedReader for input, System.out for results, and System.err for errors.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ConsoleApp {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(System.in))) {
            
            System.out.println("Welcome to the Console App!");
            System.out.print("Enter your command: ");
            
            String command = reader.readLine();
            System.out.println("Processing command: " + command);
            
        } catch (IOException e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
}

Want a simple logging mechanism? Route info to System.out and errors to System.err.

public class Logger {
    public static void info(String message) {
        System.out.println("[INFO] " + message);
    }
    
    public static void error(String message) {
        System.err.println("[ERROR] " + message);
    }
    
    public static void main(String[] args) {
        info("Application started");
        error("Configuration file not found");
        info("Application finished");
    }
}

Three streams. Three jobs. System.out for talking to users. System.err for reporting problems. System.in for getting input—though you'll wrap it with readers to make it usable. They're your program's basic I/O toolkit.

© 2026 forEach. All rights reserved.

Privacy Policy•Terms of Service