Reading text file line by line in Java

Reading text files from hard disk is quite common task in software development practice. Usually we are interested in processing it line by line. In this article I would like to present few popular ways how to do it easily using Java IO.

Reading whole file into memory

Reading a text file can be as simple as calling single Files.readAllLines() method:

Path path = Paths.get(fileName);
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
for (String line : lines) {
   System.out.println(line);
}

This method reads the whole file with given path and stores all its lines into an array of String. The rest of the code just prepares the path and prints the read lines.

While it may seem like a perfect method, it has one significant drawback. If the file being read is large, the created array will be very long. As a result memory usage of the application and the whole JVM will grow significantly which can reduce the performance of the application or in worse case kill the application with infamous OutOfMemoryError.

Therefore, usage of this method must be done with care and only in cases where the input file is small.

Reading file using BufferedReader

If you are going to read large file, you can resort to using BufferedReader class:

try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
    while (true) {
        String line = reader.readLine();
        if (line == null) {
           break;
        }
    System.out.println(line);
    }
}

First, we are creating a FileReader instance to access the given file. Because FileReader provides only very basic set of operations, we are wrapping it inside BufferedReader which has more convenient and richer interface. Finally, we call BufferedReader.readLine() method to read each line separately as long as this method returns non-null. Try-with-resources block ensures that the file is always closed at the end.

If using Java 7 or later, creation of BufferedReader can be simplified using Files class:

Path path = Paths.get(fileName);
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
    while (true) {
        String line = reader.readLine();
        if (line == null) {
           break;
        }
    System.out.println(line);
    }
}

Reading file using Java 8 streams

Java 8 brought new streams feature into the standard library. The Files class was also extended with new Files.lines() method which opens the file with given path and creates a stream with all the lines of the file. Then the stream of lines can be processed as any other stream of String including filter, map/transform and aggregate operations. In our case we print the lines only:

Path path = Paths.get(fileName);
try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
    lines.forEachOrdered(System.out::println);
}

This method has the advantage over the first presented method because the file is not read into memory at once but lazily.

Conclusion

Usage of BufferedReader is the most popular and versatile method to read a text file. If you are sure that the file is small, you can use Files.readAllLines() method to simplify the source code. The last method utilizing the streams API is very promising but requires Java 8 runtime environment which is still not an option in many cases (e.g. legacy systems, compatibility, long-running projects).

As always the source code of the example is available at GitHub.

Advertisements

About Robert Piasecki

Husband and father, Java software developer, Linux and open-source fan.
This entry was posted in Java and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s