Java IO - Reading lines using BufferedReader and Scanner

Reading data from InputStream

If you use InputStream to read some data, and if you want to read characters until new line or ‘\n’.

You should use BufferedReader with FileInputStreamReader if your read from a file

BufferedReader reader = new BufferedReader(new FileInputStreamReader(pathToFile));

or with InputStreamReader if you read from any other InputStream

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

Then read the lines like this:

String line;
while ((line = reader.readLine()) != null) {
    // process line
}

You have to test the result of the readLine() method. It will return null when you get to the end of the stream. Use readLine() and stop when it returns null.

Don’t use readLine

while(reader.ready()) {
     String line = reader.readLine();
}

because it will always return true and lead to an infinite loop.

The javadoc for the ready() method says:

Returns: True if the next read() is guaranteed not to block for input, false otherwise.

Since a readLine() at the end of stream position is guaranteed to return immediately, ready() must return true.

But if you really love InputStream then you can use a loop like this

InputStream stream;
char c;
String s = "";
do {
   c = stream.read();
   if (c == '\n')
      break;
   s += c + "";
} while (c != -1);

Use BufferedReader within the try-with block, which will close the resource after finishing with it.

try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
        String line;
        while ((line = reader.readLine()) != null) {
            // process line
        }
    }catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

It is possible to read the input stream with BufferedReader and with Scanner. If you don’t have a good reason, it is better to use BufferedReader

BufferedReader vs Scanner

Scanner is used for parsing tokens from the contents of the stream while BufferedReader just reads the stream and does not do any special parsing.

In fact you can pass a BufferedReader to a Scanner as the source of characters to parse.

The difference between BufferedReader and Scanner are following:

  1. BufferedReader is synchronized but Scanner is not synchronized.
  2. BufferedReader is thread-safe but Scanner is not thread-safe.
  3. BufferedReader has larger buffer memory but Scanner has smaller buffer memory.
  4. BufferedReader is faster but Scanner is slower in execution.
  5. BufferedReader reads data, but Scanner parses data.
  6. You can only read String using BufferedReader, using Scanner you can read to different data types like int.
  7. BufferedReader is older than Scanner, it was added on JDK 1.1, while Scanner was added on JDK 5 release.
  8. The buffer size of BufferedReader is larger (8KB) as compared to Scanner’s 1KB.
  9. BufferedReader is more suitable for reading files with long String, while Scanner is more suitable for reading small user input from command prompt.
  10. BufferedReader is synchronized, while Scanner is not, which means you cannot share Scanner among multiple threads.
  11. BufferedReader is faster than Scanner because it doesn’t spend time on parsing.
  12. BufferedReader is a bit faster as compared to Scanner.
  13. BufferedReader is from java.io package, while Scanner is from java.util package.
  14. Code to read a line from the console:
    1. BufferedReader
      InputStreamReader isr = new InputStreamReader(System.in);
      BufferedReader br = new BufferedReader(isr);
      String st = br.readLine();
      
      // You can make the object InputStreamReader object inside the BufferReader method.
      BufferReader br = new BufferedReader(InputStreamReader(System.in));
      String st = br.readLine();
      
      // You can even inspect the type of the input stream manually by using Parse method which accepts string parameter.
      int x = Integer.parseInt(br.readLine());
      
      // Or you can pass the object directly.
      int x = Integer.parseInt(st);
      
    2. Scanner
      Scanner sc = new Scanner(System.in);
      String st = sc.nextLine();
      

Reading material

  1. https://www.baeldung.com/convert-input-stream-to-string
  2. https://stackoverflow.com/questions/34954630/java-read-line-using-inputstream
  3. https://stackoverflow.com/questions/2231369/scanner-vs-bufferedreader

Links to this note