Java Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

In this article, we're going to walk through the differences between BufferedReader, Console, and Scanner classes in Java.

To have a deep dive on each topic, we suggest having a look at our individual articles on Java Scanner, Console I/O in Java, and BufferedReader.

2. User Input

Given the underlying stream passed to the constructors, both BufferedReader and Scanner classes are able to handle a wider range of user input, such as a string, file, system console (which is typically connected to the keyboard), and socket.

On the other hand, the Console class is designed to only access the character-based system console, if any, associated with the current Java virtual machine.

Let's have a look at the BufferedReader constructors, which accept different inputs:

BufferedReader br = new BufferedReader(
  new StringReader("Bufferedreader vs Console vs Scanner in Java"));
BufferedReader br = new BufferedReader(
  new FileReader("file.txt"));
BufferedReader br = new BufferedReader(
  new InputStreamReader(System.in))

Socket socket = new Socket(hostName, portNumber);
BufferedReader br =  new BufferedReader(
  new InputStreamReader(socket.getInputStream()));

The Scanner class could similarly accept different inputs in its constructors as well:

Scanner sc = new Scanner("Bufferedreader vs Console vs Scanner in Java")
Scanner sc = new Scanner(new File("file.txt"));
Scanner sc = new Scanner(System.in);

Socket socket = new Socket(hostName, portNumber);
Scanner sc =  new Scanner(socket.getInputStream());

The Console class is available only via the method call:

Console console = System.console();

Please bear in mind that when we use the Console class, the JVM associated system console isn't available if we run the code within an IDE such as Eclipse or IntelliJ IDEA.

3. User Output

In contrast to BufferedReader and Scanner classes, which don't write anything to the output stream, the Console class offers some convenient methods like readPassword (String fmt, Object… args), readLine (String fmt, Object… args), and printf (String format,Object… args)to write the prompt to the system console's output stream:

String firstName = console.readLine("Enter your first name please: ");
console.printf("Welcome " + firstName );

So when we write a program to interact with the system console, Console class will simplify the code by removing unnecessary System.out.println.

4. Parsing Input

The Scanner class can parse primitive types and strings using regular expressions.

It breaks its input into tokens using a custom delimiter pattern, which by default matches whitespace:

String input = "Bufferedreader vs Console vs Scanner";
Scanner sc = new Scanner(input).useDelimiter("\\s*vs\\s*");
System.out.println(sc.next());
System.out.println(sc.next());
System.out.println(sc.next());
sc.close();

BufferredReader and Console classes simply read the input stream as it is.

5. Reading Secure Data

The Console class has methods readPassword() and readPassword (String fmt, Object… args) to read the secure data with echoing disabled so users will not see what they are typing:

String password = String.valueOf(console.readPassword("Password :"));

BufferedReader and Scanner have no capability to do so.

6. Thread Safe

The read methods in BufferedReader and the read and write methods in Console are all synchronized, whereas those in the Scanner class are not. If we read the user input in a multi-threaded program, either BufferedReader or Console will be a better option.

7. Buffer Size

The buffer size is 8 KB in BufferedReader as compared to 1 KB in Scanner class.

In addition, we can specify the buffer size in the constructor of the BufferedReader class if needed. This will help when reading the long strings from user input. Console class has no buffer when reading from the system console, but it has a buffered output stream to write to the system console.

8. Miscellaneous

There are some differences that are not the major factors we consider when choosing the appropriate class to use in various situations.

8.1. Closing the Input Stream

Once we create the instance of BufferedReader or Scanner,  we need to remember to close it in order to avoid a memory leak. But this doesn't happen with the Console class — we don't need to close the system console after use.

8.2. Exception Handling

While Scanner and Console go with the unchecked exception approach, methods in BufferedReader throw checked exceptions, which forces us to write boilerplate try-catch syntax to handle the exceptions.

9. Conclusion

Now that we've stated the differences among these classes, let's come up with some rules of thumb regarding which one(s) are best suited to tackle different situations:

  • Use BufferedReader if we need to read long strings from a file, as it has better performance than Scanner
  • Consider Console if we're reading secure data from the system console and want to hide what is being typed
  • Use Scanner if we need to parse the input stream with a custom regular expression
  • Scanner would be preferred when we interact with the system console, as it offers fine-grained methods to read and parse the input stream. In addition, the performance drawback is not a big problem, as in most cases, the nextXXX methods are blocking and wait for manual input
  • In a thread-safe context, consider BufferedReader unless we have to use features specific to the Console class
Java bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!