reading file line by line in Java with BufferedReader

Reading files in Java is the crusade for a lot of confusion. At that place are multiple ways of accomplishing the aforementioned chore and it'due south often not clear which file reading method is best to apply. Something that's quick and dirty for a small instance file might non be the best method to use when you lot need to read a very big file. Something that worked in an earlier Java version, might non be the preferred method anymore.

This commodity aims to be the definitive guide for reading files in Java 7, 8 and 9. I'm going to cover all the means you can read files in Java. Too often, you'll read an commodity that tells you one way to read a file, only to discover later there are other ways to practise that. I'thousand actually going to cover xv different ways to read a file in Java. I'k going to embrace reading files in multiple ways with the core Java libraries likewise equally two third party libraries.

Only that's not all – what skillful is knowing how to practise something in multiple means if you don't know which way is best for your situation?

I also put each of these methods to a real performance test and document the results. That way, y'all will accept some hard data to know the performance metrics of each method.

Methodology

JDK Versions

Java code samples don't live in isolation, especially when it comes to Java I/O, every bit the API keeps evolving. All code for this commodity has been tested on:

  • Coffee SE 7 (jdk1.7.0_80)
  • Coffee SE 8 (jdk1.8.0_162)
  • Java SE 9 (jdk-ix.0.iv)

When at that place is an incompatibility, information technology will exist stated in that section. Otherwise, the code works unaltered for dissimilar Java versions. The main incompatibility is the apply of lambda expressions which was introduced in Java viii.

Coffee File Reading Libraries

In that location are multiple means of reading from files in Coffee. This article aims to be a comprehensive collection of all the dissimilar methods. I will cover:

  • java.io.FileReader.read()
  • java.io.BufferedReader.readLine()
  • coffee.io.FileInputStream.read()
  • java.io.BufferedInputStream.read()
  • java.nio.file.Files.readAllBytes()
  • java.nio.file.Files.readAllLines()
  • coffee.nio.file.Files.lines()
  • coffee.util.Scanner.nextLine()
  • org.apache.commons.io.FileUtils.readLines() – Apache Commons
  • com.google.common.io.Files.readLines() – Google Guava

Closing File Resource

Prior to JDK7, when opening a file in Java, all file resources would need to be manually airtight using a endeavour-grab-finally cake. JDK7 introduced the try-with-resources argument, which simplifies the process of endmost streams. You no longer demand to write explicit code to close streams because the JVM will automatically close the stream for you, whether an exception occurred or not. All examples used in this article apply the endeavor-with-resource statement for importing, loading, parsing and closing files.

File Location

All examples volition read test files from C:\temp.

Encoding

Character encoding is not explicitly saved with text files so Java makes assumptions nigh the encoding when reading files. Ordinarily, the assumption is correct but sometimes you lot want to be explicit when instructing your programs to read from files. When encoding isn't correct, you'll run into funny characters appear when reading files.

All examples for reading text files use two encoding variations:
Default system encoding where no encoding is specified and explicitly setting the encoding to UTF-8.

Download Code

All lawmaking files are available from Github.

Code Quality and Code Encapsulation

In that location is a deviation between writing code for your personal or work project and writing code to explain and teach concepts.

If I was writing this code for my own project, I would use proper object-oriented principles like encapsulation, brainchild, polymorphism, etc. But I wanted to make each example stand alone and easily understood, which meant that some of the code has been copied from one case to the next. I did this on purpose because I didn't want the reader to have to figure out all the encapsulation and object structures I so cleverly created. That would accept away from the examples.

For the aforementioned reason, I chose Not to write these case with a unit testing framework like JUnit or TestNG because that's not the purpose of this article. That would add another library for the reader to understand that has nothing to do with reading files in Java. That'southward why all the example are written inline within the main method, without actress methods or classes.

My main purpose is to make the examples as like shooting fish in a barrel to sympathize equally possible and I believe that having extra unit of measurement testing and encapsulation code will not assist with this. That doesn't hateful that'due south how I would encourage you to write your ain personal code. It's just the fashion I chose to write the examples in this article to make them easier to understand.

Exception Handling

All examples declare any checked exceptions in the throwing method declaration.

The purpose of this commodity is to show all the different ways to read from files in Java – it's non meant to show how to handle exceptions, which will be very specific to your state of affairs.

Then instead of creating unhelpful try catch blocks that merely print exception stack traces and ataxia upwardly the code, all example will declare whatsoever checked exception in the calling method. This will make the lawmaking cleaner and easier to understand without sacrificing whatsoever functionality.

Future Updates

As Java file reading evolves, I volition be updating this article with whatever required changes.

File Reading Methods

I organized the file reading methods into 3 groups:

  • Archetype I/O classes that accept been part of Java since before JDK one.7. This includes the java.io and java.util packages.
  • New Java I/O classes that take been part of Java since JDK1.seven. This covers the coffee.nio.file.Files class.
  • Third political party I/O classes from the Apache Commons and Google Guava projects.

Classic I/O – Reading Text

1a) FileReader – Default Encoding

FileReader reads in i character at a time, without any buffering. It's meant for reading text files. Information technology uses the default character encoding on your organization, so I have provided examples for both the default example, equally well as specifying the encoding explicitly.

          

1
2
iii
4
5
6
vii
8
nine
x
xi
12
13
14
15
xvi
17
18
19

import java.io.FileReader ;
import coffee.io.IOException ;

public class ReadFile_FileReader_Read {
public static void master( Cord [ ] pArgs) throws IOException {
Cord fileName = "c:\\temp\\sample-10KB.txt" ;

try ( FileReader fileReader = new FileReader (fileName) ) {
int singleCharInt;
char singleChar;
while ( (singleCharInt = fileReader.read ( ) ) != - 1 ) {
singleChar = ( char ) singleCharInt;

//display one character at a time
Arrangement.out.print (singleChar) ;
}
}
}
}

1b) FileReader – Explicit Encoding (InputStreamReader)

Information technology'due south actually not possible to set the encoding explicitly on a FileReader then you have to utilise the parent class, InputStreamReader and wrap it effectually a FileInputStream:

          

1
2
3
iv
v
vi
seven
eight
9
10
eleven
12
thirteen
xiv
fifteen
16
17
18
19
20
21
22

import java.io.FileInputStream ;
import java.io.IOException ;
import java.io.InputStreamReader ;

public class ReadFile_FileReader_Read_Encoding {
public static void main( String [ ] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
FileInputStream fileInputStream = new FileInputStream (fileName) ;

//specify UTF-8 encoding explicitly
try ( InputStreamReader inputStreamReader =
new InputStreamReader (fileInputStream, "UTF-8" ) ) {

int singleCharInt;
char singleChar;
while ( (singleCharInt = inputStreamReader.read ( ) ) != - 1 ) {
singleChar = ( char ) singleCharInt;
System.out.print (singleChar) ; //brandish one character at a time
}
}
}
}

2a) BufferedReader – Default Encoding

BufferedReader reads an unabridged line at a time, instead of i character at a fourth dimension like FileReader. It'southward meant for reading text files.

          

1
ii
three
4
v
half-dozen
7
8
nine
10
11
12
xiii
xiv
fifteen
16
17

import java.io.BufferedReader ;
import java.io.FileReader ;
import java.io.IOException ;

public class ReadFile_BufferedReader_ReadLine {
public static void chief( String [ ] args) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
FileReader fileReader = new FileReader (fileName) ;

attempt ( BufferedReader bufferedReader = new BufferedReader (fileReader) ) {
String line;
while ( (line = bufferedReader.readLine ( ) ) != null ) {
Organization.out.println (line) ;
}
}
}
}

2b) BufferedReader – Explicit Encoding

In a similar way to how we set encoding explicitly for FileReader, we need to create FileInputStream, wrap it inside InputStreamReader with an explicit encoding and laissez passer that to BufferedReader:

          

1
2
iii
iv
v
6
7
8
9
10
xi
12
xiii
xiv
15
16
17
18
xix
20
21
22

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

public course ReadFile_BufferedReader_ReadLine_Encoding {
public static void main( Cord [ ] args) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;

FileInputStream fileInputStream = new FileInputStream (fileName) ;

//specify UTF-8 encoding explicitly
InputStreamReader inputStreamReader = new InputStreamReader (fileInputStream, "UTF-8" ) ;

endeavor ( BufferedReader bufferedReader = new BufferedReader (inputStreamReader) ) {
String line;
while ( (line = bufferedReader.readLine ( ) ) != null ) {
Organisation.out.println (line) ;
}
}
}
}

Classic I/O – Reading Bytes

one) FileInputStream

FileInputStream reads in one byte at a time, without any buffering. While it'south meant for reading binary files such as images or audio files, it tin still be used to read text file. It's similar to reading with FileReader in that you're reading one grapheme at a time as an integer and yous need to cast that int to a char to come across the ASCII value.

By default, information technology uses the default graphic symbol encoding on your organisation, so I accept provided examples for both the default example, as well as specifying the encoding explicitly.

          

1
2
3
4
v
vi
7
8
ix
x
eleven
12
xiii
14
15
16
17
18
19
20
21

import java.io.File ;
import coffee.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.IOException ;

public class ReadFile_FileInputStream_Read {
public static void principal( String [ ] pArgs) throws FileNotFoundException, IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

try ( FileInputStream fileInputStream = new FileInputStream (file) ) {
int singleCharInt;
char singleChar;

while ( (singleCharInt = fileInputStream.read ( ) ) != - 1 ) {
singleChar = ( char ) singleCharInt;
System.out.print (singleChar) ;
}
}
}
}

2) BufferedInputStream

BufferedInputStream reads a set of bytes all at once into an internal byte array buffer. The buffer size can be set explicitly or use the default, which is what we'll demonstrate in our instance. The default buffer size appears to be 8KB but I have not explicitly verified this. All performance tests used the default buffer size so it will automatically re-size the buffer when it needs to.

          

1
2
3
4
5
6
7
eight
ix
10
xi
12
13
xiv
15
16
17
xviii
19
twenty
21
22

import java.io.BufferedInputStream ;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.IOException ;

public course ReadFile_BufferedInputStream_Read {
public static void main( Cord [ ] pArgs) throws FileNotFoundException, IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;
FileInputStream fileInputStream = new FileInputStream (file) ;

try ( BufferedInputStream bufferedInputStream = new BufferedInputStream (fileInputStream) ) {
int singleCharInt;
char singleChar;
while ( (singleCharInt = bufferedInputStream.read ( ) ) != - 1 ) {
singleChar = ( char ) singleCharInt;
System.out.print (singleChar) ;
}
}
}
}

New I/O – Reading Text

1a) Files.readAllLines() – Default Encoding

The Files class is part of the new Coffee I/O classes introduced in jdk1.vii. It but has static utility methods for working with files and directories.

The readAllLines() method that uses the default character encoding was introduced in jdk1.8 and so this example will non work in Java 7.

          

ane
2
iii
4
5
6
7
8
9
10
11
12
13
fourteen
xv
16
17

import java.io.File ;
import coffee.io.IOException ;
import coffee.nio.file.Files ;
import java.util.List ;

public class ReadFile_Files_ReadAllLines {
public static void main( String [ ] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

List fileLinesList = Files.readAllLines (file.toPath ( ) ) ;

for ( Cord line : fileLinesList) {
Organisation.out.println (line) ;
}
}
}

1b) Files.readAllLines() – Explicit Encoding

          

i
2
3
4
v
6
7
eight
9
ten
xi
12
13
14
15
16
17
18
nineteen

import java.io.File ;
import coffee.io.IOException ;
import java.nio.charset.StandardCharsets ;
import java.nio.file.Files ;
import java.util.List ;

public course ReadFile_Files_ReadAllLines_Encoding {
public static void main( String [ ] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

//employ UTF-8 encoding
List fileLinesList = Files.readAllLines (file.toPath ( ), StandardCharsets.UTF_8 ) ;

for ( String line : fileLinesList) {
System.out.println (line) ;
}
}
}

2a) Files.lines() – Default Encoding

This lawmaking was tested to piece of work in Java 8 and nine. Java vii didn't run considering of the lack of support for lambda expressions.

          

ane
2
3
iv
5
six
7
8
9
10
11
12
13
14
15
16
17

import java.io.File ;
import java.io.IOException ;
import java.nio.file.Files ;
import java.util.stream.Stream ;

public class ReadFile_Files_Lines {
public static void master( Cord [ ] pArgs) throws IOException {
Cord fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

try (Stream linesStream = Files.lines (file.toPath ( ) ) ) {
linesStream.forEach (line -> {
System.out.println (line) ;
} ) ;
}
}
}

2b) Files.lines() – Explicit Encoding

Just similar in the previous instance, this code was tested and works in Java 8 and nine simply non in Java vii.

          

i
two
three
4
5
half dozen
7
eight
9
10
11
12
13
14
15
16
17
18

import java.io.File ;
import java.io.IOException ;
import java.nio.charset.StandardCharsets ;
import java.nio.file.Files ;
import java.util.stream.Stream ;

public class ReadFile_Files_Lines_Encoding {
public static void master( String [ ] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

try (Stream linesStream = Files.lines (file.toPath ( ), StandardCharsets.UTF_8 ) ) {
linesStream.forEach (line -> {
Organisation.out.println (line) ;
} ) ;
}
}
}

3a) Scanner – Default Encoding

The Scanner class was introduced in jdk1.7 and can be used to read from files or from the console (user input).

          

i
two
three
4
five
6
vii
8
ix
10
11
12
13
xiv
15
16
17
xviii
19

import java.io.File ;
import java.io.FileNotFoundException ;
import java.util.Scanner ;

public class ReadFile_Scanner_NextLine {
public static void principal( Cord [ ] pArgs) throws FileNotFoundException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

try (Scanner scanner = new Scanner(file) ) {
Cord line;
boolean hasNextLine = simulated ;
while (hasNextLine = scanner.hasNextLine ( ) ) {
line = scanner.nextLine ( ) ;
Arrangement.out.println (line) ;
}
}
}
}

3b) Scanner – Explicit Encoding

          

1
2
3
four
5
6
7
8
9
10
11
12
xiii
fourteen
15
16
17
18
19
xx

import java.io.File ;
import coffee.io.FileNotFoundException ;
import coffee.util.Scanner ;

public grade ReadFile_Scanner_NextLine_Encoding {
public static void main( Cord [ ] pArgs) throws FileNotFoundException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

//apply UTF-8 encoding
attempt (Scanner scanner = new Scanner(file, "UTF-eight" ) ) {
String line;
boolean hasNextLine = false ;
while (hasNextLine = scanner.hasNextLine ( ) ) {
line = scanner.nextLine ( ) ;
System.out.println (line) ;
}
}
}
}

New I/O – Reading Bytes

Files.readAllBytes()

Even though the documentation for this method states that "it is non intended for reading in large files" I found this to exist the absolute best performing file reading method, even on files as large as 1GB.

          

i
two
3
four
five
6
7
8
9
10
11
12
thirteen
14
15
16
17

import coffee.io.File ;
import java.io.IOException ;
import java.nio.file.Files ;

public class ReadFile_Files_ReadAllBytes {
public static void main( Cord [ ] pArgs) throws IOException {
Cord fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

byte [ ] fileBytes = Files.readAllBytes (file.toPath ( ) ) ;
char singleChar;
for ( byte b : fileBytes) {
singleChar = ( char ) b;
Arrangement.out.print (singleChar) ;
}
}
}

tertiary Party I/O – Reading Text

Eatables – FileUtils.readLines()

Apache Commons IO is an open source Coffee library that comes with utility classes for reading and writing text and binary files. I listed it in this article because information technology tin can be used instead of the built in Java libraries. The class we're using is FileUtils.

For this article, version 2.half-dozen was used which is compatible with JDK 1.seven+

Note that yous need to explicitly specify the encoding and that method for using the default encoding has been deprecated.

          

1
2
three
four
5
half-dozen
vii
8
nine
x
eleven
12
thirteen
14
15
sixteen
17
18

import coffee.io.File ;
import java.io.IOException ;
import java.util.List ;

import org.apache.commons.io.FileUtils ;

public class ReadFile_Commons_FileUtils_ReadLines {
public static void principal( String [ ] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

List fileLinesList = FileUtils.readLines (file, "UTF-8" ) ;

for ( String line : fileLinesList) {
Organisation.out.println (line) ;
}
}
}

Guava – Files.readLines()

Google Guava is an open source library that comes with utility classes for mutual tasks similar collections handling, cache management, IO operations, string processing.

I listed it in this article considering it can be used instead of the congenital in Java libraries and I wanted to compare its functioning with the Coffee built in libraries.

For this article, version 23.0 was used.

I'm not going to examine all the dissimilar ways to read files with Guava, since this article is not meant for that. For a more detailed look at all the different ways to read and write files with Guava, have a look at Baeldung'south in depth article.

When reading a file, Guava requires that the grapheme encoding exist ready explicitly, merely like Apache Commons.

Compatibility note: This lawmaking was tested successfully on Java 8 and nine. I couldn't get it to work on Java seven and kept getting "Unsupported major.small version 52.0" error. Guava has a separate API physician for Java vii which uses a slightly different version of the Files.readLine() method. I idea I could get information technology to work merely I kept getting that fault.

          

1
2
iii
iv
v
6
7
eight
ix
10
xi
12
xiii
14
15
16
17
18
19

import java.io.File ;
import java.io.IOException ;
import coffee.util.List ;

import com.google.common.base.Charsets ;
import com.google.common.io.Files ;

public form ReadFile_Guava_Files_ReadLines {
public static void main( String [ ] args) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt" ;
File file = new File (fileName) ;

List fileLinesList = Files.readLines (file, Charsets.UTF_8 ) ;

for ( Cord line : fileLinesList) {
System.out.println (line) ;
}
}
}

Functioning Testing

Since there are then many ways to read from a file in Coffee, a natural question is "What file reading method is the best for my situation?" So I decided to test each of these methods against each other using sample data files of dissimilar sizes and timing the results.

Each code sample from this article displays the contents of the file to a string and then to the console (Organization.out). Even so, during the functioning tests the Organisation.out line was commented out since information technology would seriously tedious down the functioning of each method.

Each performance test measures the fourth dimension it takes to read in the file – line by line, character by grapheme, or byte by byte without displaying annihilation to the console. I ran each examination 5-ten times and took the boilerplate and then as not to let whatsoever outliers influence each exam. I also ran the default encoding version of each file reading method – i.e. I didn't specify the encoding explicitly.

Dev Setup

The dev surround used for these tests:

  • Intel Core i7-3615 QM @2.3 GHz, 8GB RAM
  • Windows viii x64
  • Eclipse IDE for Coffee Developers, Oxygen.2 Release (4.7.2)
  • Java SE 9 (jdk-ix.0.4)

Data Files

GitHub doesn't let pushing files larger than 100 MB, then I couldn't detect a applied way to shop my big examination files to allow others to replicate my tests. Then instead of storing them, I'm providing the tools I used to generate them then you can create test files that are similar in size to mine. Obviously they won't be the aforementioned, simply yous'll generate files that are similar in size as I used in my performance tests.

Random String Generator was used to generate sample text then I but re-create-pasted to create larger versions of the file. When the file started getting also large to manage inside a text editor, I had to utilise the control line to merge multiple text files into a larger text file:

re-create *.txt sample-1GB.txt

I created the following seven data file sizes to test each file reading method across a range of file sizes:

  • 1KB
  • 10KB
  • 100KB
  • 1MB
  • 10MB
  • 100MB
  • 1GB

Performance Summary

There were some surprises and some expected results from the performance tests.

As expected, the worst performers were the methods that read in a file character past character or byte by byte. Simply what surprised me was that the native Coffee IO libraries outperformed both 3rd political party libraries – Apache Commons IO and Google Guava.

What's more than – both Google Guava and Apache Eatables IO threw a java.lang.OutOfMemoryError when trying to read in the 1 GB test file. This also happened with the Files.readAllLines(Path) method but the remaining 7 methods were able to read in all test files, including the 1GB exam file.

The post-obit table summarizes the average time (in milliseconds) each file reading method took to complete. I highlighted the top three methods in green, the boilerplate performing methods in yellow and the worst performing methods in red:

The following nautical chart summarizes the in a higher place tabular array but with the following changes:

I removed java.io.FileInputStream.read() from the chart because its operation was so bad it would skew the unabridged chart and yous wouldn't see the other lines properly
I summarized the information from 1KB to 1MB because later on that, the chart would get too skewed with and so many under performers and besides some methods threw a java.lang.OutOfMemoryError at 1GB

The Winners

The new Coffee I/O libraries (java.nio) had the best overall winner (java.nio.Files.readAllBytes()) just it was followed closely backside past BufferedReader.readLine() which was also a proven height performer beyond the board. The other splendid performer was java.nio.Files.lines(Path) which had slightly worse numbers for smaller test files but really excelled with the larger test files.

The absolute fastest file reader across all data tests was java.nio.Files.readAllBytes(Path). It was consistently the fastest and even reading a 1GB file only took nearly 1 2nd.

The following nautical chart compares performance for a 100KB test file:

You can run into that the lowest times were for Files.readAllBytes(), BufferedInputStream.read() and BufferedReader.readLine().

The following chart compares performance for reading a 10MB file. I didn't bother including the bar for FileInputStream.Read() considering the performance was so bad information technology would skew the entire chart and yous couldn't tell how the other methods performed relative to each other:

Files.readAllBytes() really outperforms all other methods and BufferedReader.readLine() is a distant 2nd.

The Losers

As expected, the absolute worst performer was java.io.FileInputStream.read() which was orders of magnitude slower than its rivals for most tests. FileReader.read() was as well a poor performer for the same reason – reading files byte by byte (or graphic symbol by graphic symbol) instead of with buffers drastically degrades performance.

Both the Apache Eatables IO FileUtils.readLines() and Guava Files.readLines() crashed with an OutOfMemoryError when trying to read the 1GB test file and they were about average in operation for the remaining exam files.

java.nio.Files.readAllLines() also crashed when trying to read the 1GB exam file but information technology performed quite well for smaller file sizes.

Operation Rankings

Here's a ranked list of how well each file reading method did, in terms of speed and handling of large files, likewise as compatibility with different Java versions.

Rank File Reading Method
1 coffee.nio.file.Files.readAllBytes()
2 coffee.io.BufferedFileReader.readLine()
3 coffee.nio.file.Files.lines()
4 java.io.BufferedInputStream.read()
5 java.util.Scanner.nextLine()
vi coffee.nio.file.Files.readAllLines()
vii org.apache.commons.io.FileUtils.readLines()
eight com.google.mutual.io.Files.readLines()
ix java.io.FileReader.read()
x java.io.FileInputStream.Read()

Conclusion

I tried to present a comprehensive prepare of methods for reading files in Java, both text and binary. We looked at 15 different ways of reading files in Java and we ran functioning tests to come across which methods are the fastest.

The new Java IO library (java.nio) proved to exist a great performer just and then was the classic BufferedReader.