reading file line by line in Java with BufferedReader

Reading files in Java is the cause for a lot of confusion. At that place are multiple ways of accomplishing the same chore and information technology's often not clear which file reading method is all-time to use. Something that's quick and muddy for a pocket-size example file might not be the best method to use when y'all need to read a very large file. Something that worked in an before Java version, might not be the preferred method anymore.

This article aims to be the definitive guide for reading files in Coffee vii, viii and 9. I'm going to cover all the means you can read files in Java. Too frequently, you'll read an article that tells you lot i manner to read a file, but to find afterward there are other ways to do that. I'm actually going to cover fifteen different means to read a file in Java. I'm going to comprehend reading files in multiple ways with the core Coffee libraries as well as two third party libraries.

Merely that's not all – what good is knowing how to do something in multiple ways if y'all don't know which manner is best for your situation?

I too put each of these methods to a real functioning test and document the results. That fashion, 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, peculiarly when information technology comes to Java I/O, as the API keeps evolving. All code for this article has been tested on:

  • Java SE 7 (jdk1.vii.0_80)
  • Java SE 8 (jdk1.8.0_162)
  • Java SE 9 (jdk-9.0.4)

When there is an incompatibility, it will be stated in that section. Otherwise, the code works unaltered for dissimilar Java versions. The main incompatibility is the use of lambda expressions which was introduced in Java eight.

Coffee File Reading Libraries

There are multiple ways of reading from files in Java. This article aims to be a comprehensive drove of all the different 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()
  • java.util.Scanner.nextLine()
  • org.apache.eatables.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 resource would demand to be manually airtight using a try-grab-finally block. JDK7 introduced the try-with-resources statement, which simplifies the process of closing streams. You no longer need to write explicit lawmaking to close streams because the JVM will automatically shut the stream for you lot, whether an exception occurred or non. All examples used in this article apply the effort-with-resource statement for importing, loading, parsing and endmost files.

File Location

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

Encoding

Graphic symbol encoding is non explicitly saved with text files and so Java makes assumptions about the encoding when reading files. Normally, the supposition is correct but sometimes you want to exist explicit when instructing your programs to read from files. When encoding isn't correct, you'll see funny characters appear when reading files.

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

Download Code

All code files are available from Github.

Code Quality and Code Encapsulation

There is a difference betwixt writing code for your personal or work project and writing code to explain and teach concepts.

If I was writing this code for my ain project, I would apply proper object-oriented principles like encapsulation, abstraction, polymorphism, etc. Just I wanted to make each example stand solitary and easily understood, which meant that some of the code has been copied from i example to the side by side. I did this on purpose because I didn't desire the reader to have to figure out all the encapsulation and object structures I and so cleverly created. That would have away from the examples.

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

My main purpose is to make the examples as easy to understand as possible and I believe that having extra unit of measurement testing and encapsulation code will not help with this. That doesn't mean that'due south how I would encourage you lot to write your own personal lawmaking. Information technology's just the fashion I chose to write the examples in this article to make them easier to empathize.

Exception Handling

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

The purpose of this article is to show all the different ways to read from files in Java – it'due south not meant to testify how to handle exceptions, which will exist very specific to your state of affairs.

So instead of creating unhelpful try take hold of blocks that just print exception stack traces and clutter up the code, all example volition declare any checked exception in the calling method. This will brand the code cleaner and easier to understand without sacrificing any functionality.

Futurity Updates

As Java file reading evolves, I volition exist updating this commodity with any required changes.

File Reading Methods

I organized the file reading methods into 3 groups:

  • Classic I/O classes that have been part of Java since before JDK 1.seven. This includes the java.io and coffee.util packages.
  • New Coffee I/O classes that have been part of Java since JDK1.vii. This covers the java.nio.file.Files grade.
  • Third party I/O classes from the Apache Commons and Google Guava projects.

Archetype I/O – Reading Text

1a) FileReader – Default Encoding

FileReader reads in one character at a time, without whatsoever buffering. It'south meant for reading text files. It uses the default graphic symbol encoding on your system, then I accept provided examples for both the default example, too equally specifying the encoding explicitly.

          

i
two
3
four
5
6
seven
eight
nine
10
11
12
thirteen
fourteen
15
16
17
18
19

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

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

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

//display one character at a time
Organisation.out.impress (singleChar) ;
}
}
}
}

1b) FileReader – Explicit Encoding (InputStreamReader)

It's really not possible to set the encoding explicitly on a FileReader and so you have to use the parent grade, InputStreamReader and wrap information technology around a FileInputStream:

          

1
2
iii
4
v
6
7
eight
ix
10
11
12
13
14
15
16
17
eighteen
19
20
21
22

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

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

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

int singleCharInt;
char singleChar;
while ( (singleCharInt = inputStreamReader.read ( ) ) != - 1 ) {
singleChar = ( char ) singleCharInt;
Organisation.out.print (singleChar) ; //display one character at a fourth dimension
}
}
}
}

2a) BufferedReader – Default Encoding

BufferedReader reads an unabridged line at a fourth dimension, instead of one grapheme at a time like FileReader. It's meant for reading text files.

          

ane
2
3
4
5
6
7
viii
ix
10
11
12
13
xiv
fifteen
sixteen
17

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

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

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

2b) BufferedReader – Explicit Encoding

In a similar style to how we set encoding explicitly for FileReader, we need to create FileInputStream, wrap it within InputStreamReader with an explicit encoding and pass that to BufferedReader:

          

1
2
iii
4
5
half-dozen
7
8
9
10
11
12
13
fourteen
15
16
17
xviii
19
20
21
22

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

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

FileInputStream fileInputStream = new FileInputStream (fileName) ;

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

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

Archetype I/O – Reading Bytes

1) FileInputStream

FileInputStream reads in one byte at a fourth dimension, without whatever buffering. While information technology'due south meant for reading binary files such every bit images or audio files, it tin even so be used to read text file. It's similar to reading with FileReader in that you're reading one graphic symbol at a time as an integer and yous need to cast that int to a char to come across the ASCII value.

By default, it uses the default character encoding on your organization, so I have provided examples for both the default instance, besides as specifying the encoding explicitly.

          

1
two
three
4
five
vi
vii
8
nine
x
11
12
13
14
15
16
17
18
19
20
21

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

public class ReadFile_FileInputStream_Read {
public static void primary( Cord [ ] 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;
Arrangement.out.impress (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 example. The default buffer size appears to be 8KB only I have not explicitly verified this. All performance tests used the default buffer size and then it will automatically re-size the buffer when it needs to.

          

one
two
3
4
5
vi
vii
viii
9
ten
11
12
13
14
15
sixteen
17
18
nineteen
20
21
22

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

public form ReadFile_BufferedInputStream_Read {
public static void master( 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 ( ) ) != - one ) {
singleChar = ( char ) singleCharInt;
Organisation.out.print (singleChar) ;
}
}
}
}

New I/O – Reading Text

1a) Files.readAllLines() – Default Encoding

The Files grade is function of the new Java I/O classes introduced in jdk1.seven. Information technology only has static utility methods for working with files and directories.

The readAllLines() method that uses the default graphic symbol encoding was introduced in jdk1.viii then this example will not work in Java seven.

          

1
2
3
four
five
vi
vii
8
9
10
11
12
13
14
15
sixteen
17

import java.io.File ;
import java.io.IOException ;
import java.nio.file.Files ;
import java.util.Listing ;

public form 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 ( String line : fileLinesList) {
System.out.println (line) ;
}
}
}

1b) Files.readAllLines() – Explicit Encoding

          

1
2
iii
four
5
6
vii
8
ix
ten
xi
12
13
14
15
sixteen
17
18
19

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

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

//use 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 code was tested to work in Coffee 8 and 9. Java 7 didn't run considering of the lack of support for lambda expressions.

          

1
two
iii
4
5
6
7
8
9
x
11
12
13
fourteen
xv
xvi
17

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

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

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

2b) Files.lines() – Explicit Encoding

Just like in the previous example, this lawmaking was tested and works in Java 8 and 9 simply not in Java vii.

          

1
2
three
4
5
6
7
viii
nine
x
11
12
13
fourteen
15
xvi
17
18

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

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

endeavour (Stream linesStream = Files.lines (file.toPath ( ), StandardCharsets.UTF_8 ) ) {
linesStream.forEach (line -> {
System.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).

          

1
2
3
4
5
six
seven
eight
9
10
11
12
13
14
fifteen
xvi
17
18
xix

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

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

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

3b) Scanner – Explicit Encoding

          

1
2
three
four
v
vi
7
8
9
x
11
12
xiii
14
xv
16
17
18
xix
twenty

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

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

//use UTF-8 encoding
try (Scanner scanner = new Scanner(file, "UTF-8" ) ) {
Cord line;
boolean hasNextLine = false ;
while (hasNextLine = scanner.hasNextLine ( ) ) {
line = scanner.nextLine ( ) ;
Organization.out.println (line) ;
}
}
}
}

New I/O – Reading Bytes

Files.readAllBytes()

Even though the documentation for this method states that "it is not intended for reading in large files" I found this to be the absolute all-time performing file reading method, even on files as large as 1GB.

          

1
2
3
4
5
6
7
viii
ix
10
11
12
xiii
xiv
15
sixteen
17

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

public form ReadFile_Files_ReadAllBytes {
public static void main( String [ ] pArgs) throws IOException {
String 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;
System.out.print (singleChar) ;
}
}
}

tertiary Party I/O – Reading Text

Commons – FileUtils.readLines()

Apache Eatables IO is an open source Java library that comes with utility classes for reading and writing text and binary files. I listed it in this article because information technology tin 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 one.7+

Notation that you lot demand to explicitly specify the encoding and that method for using the default encoding has been deprecated.

          

1
2
3
iv
five
6
vii
8
9
10
11
12
13
xiv
15
16
17
18

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

import org.apache.commons.io.FileUtils ;

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

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

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

Guava – Files.readLines()

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

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

For this article, version 23.0 was used.

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

When reading a file, Guava requires that the character encoding be gear up explicitly, but like Apache Commons.

Compatibility note: This code was tested successfully on Java 8 and ix. I couldn't go it to work on Java 7 and kept getting "Unsupported major.small-scale version 52.0" mistake. Guava has a carve up API physician for Coffee vii which uses a slightly different version of the Files.readLine() method. I thought I could go it to work but I kept getting that mistake.

          

1
ii
three
4
5
6
7
viii
9
10
11
12
13
fourteen
15
16
17
eighteen
19

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

import com.google.mutual.base of operations.Charsets ;
import com.google.common.io.Files ;

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

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

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

Performance Testing

Since in that location are then many ways to read from a file in Java, a natural question is "What file reading method is the best for my state of affairs?" So I decided to exam each of these methods against each other using sample information files of different sizes and timing the results.

Each code sample from this article displays the contents of the file to a string and then to the panel (Organisation.out). Nevertheless, during the operation tests the System.out line was commented out since information technology would seriously boring down the performance of each method.

Each performance exam measures the time it takes to read in the file – line past line, character by graphic symbol, or byte past byte without displaying anything to the console. I ran each test 5-10 times and took the average so every bit not to let whatever outliers influence each examination. 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 surroundings used for these tests:

  • Intel Cadre i7-3615 QM @2.3 GHz, 8GB RAM
  • Windows 8 x64
  • Eclipse IDE for Java Developers, Oxygen.2 Release (4.7.two)
  • Java SE 9 (jdk-9.0.four)

Data Files

GitHub doesn't allow pushing files larger than 100 MB, then I couldn't notice a applied way to store my large test files to allow others to replicate my tests. So instead of storing them, I'thou providing the tools I used to generate them and then you can create examination files that are similar in size to mine. Plainly they won't be the aforementioned, but y'all'll generate files that are similar in size as I used in my operation tests.

Random String Generator was used to generate sample text and so I just copy-pasted to create larger versions of the file. When the file started getting too large to manage inside a text editor, I had to utilize the control line to merge multiple text files into a larger text file:

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

I created the following 7 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 by character or byte by byte. But what surprised me was that the native Java IO libraries outperformed both third political party libraries – Apache Commons IO and Google Guava.

What's more – both Google Guava and Apache Commons IO threw a java.lang.OutOfMemoryError when trying to read in the i 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 following table summarizes the average fourth dimension (in milliseconds) each file reading method took to consummate. I highlighted the top three methods in greenish, the average performing methods in yellow and the worst performing methods in red:

The following chart summarizes the to a higher place table but with the following changes:

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

The Winners

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

The absolute fastest file reader across all data tests was coffee.nio.Files.readAllBytes(Path). It was consistently the fastest and fifty-fifty reading a 1GB file just took about ane second.

The following chart compares performance for a 100KB exam 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() because 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 second.

The Losers

Equally expected, the accented worst performer was java.io.FileInputStream.read() which was orders of magnitude slower than its rivals for about tests. FileReader.read() was also a poor performer for the same reason – reading files byte by byte (or character past graphic symbol) instead of with buffers drastically degrades performance.

Both the Apache Commons 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 functioning for the remaining test files.

java.nio.Files.readAllLines() likewise crashed when trying to read the 1GB test file simply it performed quite well for smaller file sizes.

Performance Rankings

Here'south a ranked listing of how well each file reading method did, in terms of speed and handling of large files, as well as compatibility with dissimilar Java versions.

Rank File Reading Method
i java.nio.file.Files.readAllBytes()
2 java.io.BufferedFileReader.readLine()
3 coffee.nio.file.Files.lines()
4 coffee.io.BufferedInputStream.read()
5 java.util.Scanner.nextLine()
6 java.nio.file.Files.readAllLines()
7 org.apache.commons.io.FileUtils.readLines()
8 com.google.common.io.Files.readLines()
9 java.io.FileReader.read()
x java.io.FileInputStream.Read()

Determination

I tried to nowadays a comprehensive set of methods for reading files in Java, both text and binary. We looked at 15 dissimilar ways of reading files in Coffee and we ran operation tests to encounter which methods are the fastest.

The new Java IO library (java.nio) proved to be a dandy performer but and so was the classic BufferedReader.