A Guide to the Java FileReader Class

A Guide to the Java FileReader Class

In this tutorial, we'll learn the basic concept of a Reader and how we can use the FileReader class for doing read operations on a character stream in Java.

Originally published at https://www.baeldung.com

1. Overview

As the name suggests, FileReader is a Java class that makes it easy to read the contents of a file.

In this tutorial, we'll learn the basic concept of a Reader and how we can use the FileReader class for doing read operations on a character stream in Java.

2. Reader Basics

If we look at the code of the FileReader class, then we'll notice that the class contains minimal code for creating a FileReader object and no other methods.

This raises questions like “Who does the heavy lifting behind this class?”

To answer this question, we must understand the concept and hierarchy of the Reader class in Java.

Reader is an abstract base class that makes reading characters possible through one of its concrete implementations. It defines the following basic operations of reading characters from any medium such as memory or the filesystem:

  • Read a single character
  • Read an array of characters
  • Mark and reset a given position in a stream of characters
  • Skip position while reading a character stream
  • Close the input stream

Naturally, all the implementations of Reader class must implement all the abstract methods, namely read() and close(). Moreover, most implementations also override other inherited methods to give additional functionality or better performance.

2.1. When to Use a FileReader

Now that we've some understanding about a Reader, we're ready to bring our focus back to the FileReader class.

FileReader inherits its functionality from InputStreamReader, which is a Reader implementation designed to read bytes from an input stream as characters.

Let's see this hierarchy in the class definitions:

public class InputStreamReader extends Reader {}
 
public class FileReader extends InputStreamReader {}

In general, we can use an InputStreamReader for reading characters from any input source.

However, when it comes to reading text from a file, using an InputStreamReader would be like cutting an apple with a sword. Of course, the right tool would be a knife, which is precisely what FileReader promises.

We can use a FileReader when we want to read text from a file using the system's default character set. For any other advanced functionality, it'd be ideal for making use of InputStreamReader class directly.

3. Reading a Text File with a FileReader

Let's walk through a coding exercise of reading characters from a HelloWorld.txt file using a FileReader instance.

3.1. Creating a FileReader

As a convenience class, FileReader offers three overloaded constructors that can be used to initialize a reader that can read from a file as an input source.

Let's take a look at these constructors:

public FileReader(String fileName) throws FileNotFoundException {
    super(new FileInputStream(fileName));
}
 
public FileReader(File file) throws FileNotFoundException {
    super(new FileInputStream(file));
}
 
public FileReader(FileDescriptor fd) {
    super(new FileInputStream(fd));
}

In our case, we know the filename of the input file. Consequently, we can use the first constructor to initialize a reader:

FileReader fileReader = new FileReader(path);

3.2. Reading a Single Character

Next, let's create readAllCharactersOneByOne(), a method for reading characters from the file one at a time:

public static String readAllCharactersOneByOne(Reader reader) throws IOException {
    StringBuilder content = new StringBuilder();
    int nextChar;
    while ((nextChar = reader.read()) != -1) {
        content.append((char) nextChar);
    }
    return String.valueOf(content);
}

As we can see from the above code, we've used the read() method in a loop to read characters one by one until it returns -1, meaning there're no more characters to read.

Now, let's test our code by validating that the text read from the file matches the expected text:

@Test
public void givenFileReader_whenReadAllCharacters_thenReturnsContent() throws IOException {
    String expectedText = "Hello, World!";
    File file = new File(FILE_PATH);
    try (FileReader fileReader = new FileReader(file)) {
        String content = FileReaderExample.readAllCharactersOneByOne(fileReader);
        Assert.assertEquals(expectedText, content);
    }
}

3.3. Reading of an Array of Characters

We can even read multiple characters at once using the inherited read(char cbuf[], int off, int len) method:

public static String readMultipleCharacters(Reader reader, int length) throws IOException {
    char[] buffer = new char[length];
    int charactersRead = reader.read(buffer, 0, length);
    if (charactersRead != -1) {
        return new String(buffer, 0, charactersRead);
    } else {
        return "";
    }
}

There's a subtle difference in the return value of read() when it comes to reading multiple characters in an array. The return value here is either the number of characters read or -1 if the reader has reached the end of the input stream.

Next, let's test the correctness of our code:

@Test
public void givenFileReader_whenReadMultipleCharacters_thenReturnsContent() throws IOException {
    String expectedText = "Hello";
    File file = new File(FILE_PATH);
    try (FileReader fileReader = new FileReader(file)) {
        String content = FileReaderExample.readMultipleCharacters(fileReader, 5);
        Assert.assertEquals(expectedText, content);
    }
}

4. Limitations

We've seen that the FileReader class relies on the default system character encoding.

So, for situations, where we need to use custom values for the character set, buffer size, or input stream, we must use InputStreamReader.

Moreover, we all know that I/O cycles are expensive and can introduce latency to our application. So, it's in our best interest to minimize the number of I/O operations by wrapping a BufferedReader around our FileReader object:

BufferedReader in = new BufferedReader(fileReader);

5. Conclusion

In this tutorial, we learned about the basic concepts of a Reader and how FileReader makes it simple to do read operations on text files though some examples.

As always, the complete source code for the tutorial is available on GitHub.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Java Tutorial for Absolute Beginners

100+ Java Interview Questions and Answers In 2019

Python vs Java: Understand Object Oriented Programming

Angular 7 + Spring Boot CRUD Example


java

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

How to Install OpenJDK 11 on CentOS 8

What is OpenJDK? OpenJDk or Open Java Development Kit is a free, open-source framework of the Java Platform, Standard Edition (or Java SE).

Java Core (2020) | Java for beginners | Brush up your Java Skills | Get Hired

In this video we will learn about all the major concepts that come under Java Core . The course is very carefully designed and is made with keeping simplicit...

Best Ways To Improve Skills In Java and Python Programming

Join CETPA, India's best institute for Java online training and Certification Course. Enroll now to learn Core to Advanced Java & avail 50% discount on Java Online Course with Certificate.

Java Fundamentals: Learn Java for absolute beginners |Simpliv

Java Fundamentals: Learn Java for absolute beginners

Java For Loop Example | For Loop in Java Tutorial

Java For loop provides a concise way of writing the loop structure. For loop consumes the initialization, condition and increment/decrement in one line.