reading file line by line in Java with BufferedReader

Reading files in Java is the crusade for a lot of defoliation. There are multiple ways of accomplishing the same job and it's often not clear which file reading method is best to use. Something that'south quick and muddied for a small-scale instance file might non be the best method to utilise when you need to read a very large file. Something that worked in an earlier Coffee version, might not be the preferred method anymore.

This article aims to exist the definitive guide for reading files in Java 7, eight and 9. I'm going to cover all the ways you can read files in Coffee. Likewise often, you'll read an article that tells you one way to read a file, only to discover later there are other means to do that. I'chiliad really going to cover 15 different ways to read a file in Coffee. I'1000 going to comprehend reading files in multiple means with the cadre Java libraries likewise as 2 tertiary party libraries.

Just that's not all – what good is knowing how to exercise something in multiple ways if you don't know which way is all-time for your situation?

I likewise put each of these methods to a existent operation test and document the results. That way, yous will accept some hard data to know the performance metrics of each method.

Methodology

JDK Versions

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

  • Coffee SE 7 (jdk1.seven.0_80)
  • Coffee SE eight (jdk1.8.0_162)
  • Coffee SE 9 (jdk-nine.0.four)

When at that place is an incompatibility, it volition be stated in that section. Otherwise, the lawmaking works unaltered for different Java versions. The principal incompatibility is the use of lambda expressions which was introduced in Coffee eight.

Coffee File Reading Libraries

There are multiple ways of reading from files in Java. This article aims to exist a comprehensive drove of all the different methods. I will cover:

  • java.io.FileReader.read()
  • java.io.BufferedReader.readLine()
  • java.io.FileInputStream.read()
  • coffee.io.BufferedInputStream.read()
  • java.nio.file.Files.readAllBytes()
  • java.nio.file.Files.readAllLines()
  • java.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 Resources

Prior to JDK7, when opening a file in Java, all file resource would need to exist manually closed using a attempt-grab-finally block. JDK7 introduced the effort-with-resources statement, which simplifies the procedure of closing streams. You no longer need 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 commodity utilize the try-with-resources argument for importing, loading, parsing and closing files.

File Location

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

Encoding

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

All examples for reading text files utilise two encoding variations:
Default arrangement 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 Lawmaking Encapsulation

In that location 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 own project, I would use proper object-oriented principles similar encapsulation, abstraction, polymorphism, etc. Only I wanted to make each example stand up alone and hands understood, which meant that some of the code has been copied from one example to the next. I did this on purpose because I didn't desire the reader to have to figure out all the encapsulation and object structures I so cleverly created. That would take away from the examples.

For the aforementioned reason, I chose Non to write these example with a unit testing framework similar JUnit or TestNG considering that's not the purpose of this commodity. That would add another library for the reader to understand that has nix to do with reading files in Coffee. That'due south why all the example are written inline inside the main method, without extra methods or classes.

My main purpose is to make the examples every bit like shooting fish in a barrel to understand as possible and I believe that having extra unit of measurement testing and encapsulation code will not aid with this. That doesn't mean that's how I would encourage you to write your ain personal code. It's simply the way I chose to write the examples in this commodity to make them easier to understand.

Exception Handling

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

The purpose of this article is to show all the unlike ways to read from files in Java – information technology's not meant to prove how to handle exceptions, which will exist very specific to your situation.

So instead of creating unhelpful endeavour catch blocks that but impress 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 empathise without sacrificing whatever functionality.

Future Updates

As Java file reading evolves, I will be updating this article with any required changes.

File Reading Methods

I organized the file reading methods into three groups:

  • Classic I/O classes that have been part of Java since before JDK 1.7. This includes the coffee.io and java.util packages.
  • New Java I/O classes that have been office of Java since JDK1.7. This covers the coffee.nio.file.Files class.
  • Third 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 whatever buffering. It's meant for reading text files. It uses the default character encoding on your organization, so I take provided examples for both the default example, as well as specifying the encoding explicitly.

          

i
ii
3
iv
five
6
7
8
9
10
xi
12
xiii
fourteen
15
16
17
18
nineteen

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

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

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

//display ane character at a fourth dimension
System.out.print (singleChar) ;
}
}
}
}

1b) FileReader – Explicit Encoding (InputStreamReader)

It's actually not possible to set up the encoding explicitly on a FileReader so you take to use the parent form, InputStreamReader and wrap it around a FileInputStream:

          

i
2
3
iv
five
6
7
eight
ix
10
11
12
13
xiv
15
16
17
18
19
20
21
22

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

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

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

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

2a) BufferedReader – Default Encoding

BufferedReader reads an entire line at a time, instead of one character at a time like FileReader. It'south meant for reading text files.

          

one
2
iii
iv
five
half-dozen
7
viii
nine
x
eleven
12
xiii
xiv
15
16
17

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

public form ReadFile_BufferedReader_ReadLine {
public static void main( String [ ] args) throws IOException {
String 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 information technology inside InputStreamReader with an explicit encoding and laissez passer that to BufferedReader:

          

one
2
3
4
five
half dozen
7
8
9
10
11
12
13
xiv
15
16
17
18
19
twenty
21
22

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

public class ReadFile_BufferedReader_ReadLine_Encoding {
public static void chief( 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" ) ;

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 ane byte at a time, without any buffering. While it's meant for reading binary files such as images or audio files, it tin still exist used to read text file. Information technology's similar to reading with FileReader in that you're reading i character at a time as an integer and you demand to cast that int to a char to meet the ASCII value.

By default, information technology uses the default character encoding on your arrangement, so I take provided examples for both the default case, as well every bit specifying the encoding explicitly.

          

1
2
three
iv
five
6
vii
8
9
10
eleven
12
13
14
15
xvi
17
18
19
twenty
21

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

public class ReadFile_FileInputStream_Read {
public static void main( String [ ] pArgs) throws FileNotFoundException, IOException {
Cord 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 one time into an internal byte assortment buffer. The buffer size can be gear up explicitly or employ the default, which is what we'll demonstrate in our example. The default buffer size appears to exist 8KB but I accept not explicitly verified this. All operation tests used the default buffer size so it will automatically re-size the buffer when it needs to.

          

one
ii
3
4
5
6
7
8
9
x
11
12
13
14
15
xvi
17
18
19
20
21
22

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

public form ReadFile_BufferedInputStream_Read {
public static void main( String [ ] 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;
System.out.impress (singleChar) ;
}
}
}
}

New I/O – Reading Text

1a) Files.readAllLines() – Default Encoding

The Files form is part of the new Java I/O classes introduced in jdk1.7. It only has static utility methods for working with files and directories.

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

          

1
2
iii
4
5
6
seven
viii
9
10
eleven
12
13
fourteen
15
16
17

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

public class ReadFile_Files_ReadAllLines {
public static void principal( 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
4
5
6
vii
8
9
10
11
12
13
xiv
15
16
17
18
19

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

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

//utilize 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 work in Coffee 8 and 9. Java seven didn't run because of the lack of support for lambda expressions.

          

i
2
3
4
5
half dozen
7
viii
9
ten
11
12
xiii
14
15
16
17

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

public class ReadFile_Files_Lines {
public static void main( String [ ] 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 -> {
System.out.println (line) ;
} ) ;
}
}
}

2b) Files.lines() – Explicit Encoding

Just similar in the previous example, this code was tested and works in Coffee 8 and 9 simply non in Java vii.

          

1
two
three
iv
5
half-dozen
vii
8
ix
10
11
12
13
xiv
fifteen
16
17
18

import java.io.File ;
import java.io.IOException ;
import java.nio.charset.StandardCharsets ;
import java.nio.file.Files ;
import coffee.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 -> {
System.out.println (line) ;
} ) ;
}
}
}

3a) Scanner – Default Encoding

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

          

1
2
iii
4
five
6
7
8
nine
x
11
12
thirteen
fourteen
15
16
17
18
xix

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

public form 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) ) {
String line;
boolean hasNextLine = imitation ;
while (hasNextLine = scanner.hasNextLine ( ) ) {
line = scanner.nextLine ( ) ;
System.out.println (line) ;
}
}
}
}

3b) Scanner – Explicit Encoding

          

ane
2
3
iv
5
half-dozen
7
eight
9
10
11
12
13
xiv
15
16
17
18
xix
20

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

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

//utilise UTF-viii encoding
endeavour (Scanner scanner = new Scanner(file, "UTF-8" ) ) {
String line;
boolean hasNextLine = false ;
while (hasNextLine = scanner.hasNextLine ( ) ) {
line = scanner.nextLine ( ) ;
Organisation.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 big files" I plant this to be the absolute all-time performing file reading method, fifty-fifty on files as big as 1GB.

          

1
2
3
four
5
6
seven
viii
9
x
xi
12
xiii
14
15
16
17

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

public class ReadFile_Files_ReadAllBytes {
public static void master( 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) ;
}
}
}

3rd Political party I/O – Reading Text

Commons – FileUtils.readLines()

Apache Commons 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 Coffee libraries. The class we're using is FileUtils.

For this commodity, version 2.half-dozen was used which is uniform with JDK ane.vii+

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

          

1
2
iii
4
5
6
vii
8
9
10
11
12
13
fourteen
15
sixteen
17
18

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

import org.apache.commons.io.FileUtils ;

public course 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) {
System.out.println (line) ;
}
}
}

Guava – Files.readLines()

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

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

For this commodity, version 23.0 was used.

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

When reading a file, Guava requires that the character encoding be set explicitly, only similar Apache Commons.

Compatibility notation: This lawmaking was tested successfully on Java eight and 9. I couldn't get information technology to work on Java 7 and kept getting "Unsupported major.minor version 52.0" error. Guava has a separate API medico for Java 7 which uses a slightly different version of the Files.readLine() method. I thought I could go it to work simply I kept getting that mistake.

          

i
two
3
4
5
6
vii
viii
9
ten
11
12
xiii
14
15
16
17
18
19

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

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

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

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

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

Functioning Testing

Since at that place are so 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 examination each of these methods against each other using sample data files of dissimilar sizes and timing the results.

Each code sample from this commodity displays the contents of the file to a cord and so to the console (System.out). However, during the operation tests the System.out line was commented out since it would seriously slow downwardly the performance of each method.

Each functioning exam measures the time it takes to read in the file – line past line, grapheme by graphic symbol, or byte past byte without displaying anything to the console. I ran each test 5-x times and took the average and then as not to let any outliers influence each test. I too ran the default encoding version of each file reading method – i.e. I didn't specify the encoding explicitly.

Dev Setup

The dev environment used for these tests:

  • Intel Core i7-3615 QM @two.3 GHz, 8GB RAM
  • Windows 8 x64
  • Eclipse IDE for Java Developers, Oxygen.2 Release (4.7.2)
  • Java SE 9 (jdk-9.0.iv)

Data Files

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

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

copy *.txt sample-1GB.txt

I created the following 7 information file sizes to exam each file reading method across a range of file sizes:

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

Performance Summary

At that place 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 graphic symbol or byte by byte. Only what surprised me was that the native Java IO libraries outperformed both 3rd party libraries – Apache Commons IO and Google Guava.

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

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

The post-obit chart summarizes the higher up table but with the following changes:

I removed coffee.io.FileInputStream.read() from the chart because its performance was so bad it would skew the entire chart and you lot wouldn't meet the other lines properly
I summarized the data from 1KB to 1MB because after that, the chart would go besides skewed with so many under performers and also 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()) just it was followed closely behind by BufferedReader.readLine() which was also a proven elevation performer across the board. The other first-class 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 information tests was java.nio.Files.readAllBytes(Path). It was consistently the fastest and even reading a 1GB file only took almost i second.

The post-obit nautical chart compares performance for a 100KB examination file:

Yous can encounter that the lowest times were for Files.readAllBytes(), BufferedInputStream.read() and BufferedReader.readLine().

The following chart compares operation for reading a 10MB file. I didn't carp including the bar for FileInputStream.Read() because the performance was so bad information technology would skew the unabridged chart and you lot 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

As expected, the absolute worst performer was java.io.FileInputStream.read() which was orders of magnitude slower than its rivals for nigh tests. FileReader.read() was too a poor performer for the same reason – reading files byte by byte (or character by character) 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 performance for the remaining exam files.

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

Performance Rankings

Hither's a ranked list of how well each file reading method did, in terms of speed and treatment of large files, equally well as compatibility with different Coffee versions.

Rank File Reading Method
ane coffee.nio.file.Files.readAllBytes()
two java.io.BufferedFileReader.readLine()
3 java.nio.file.Files.lines()
4 java.io.BufferedInputStream.read()
five 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()
10 java.io.FileInputStream.Read()

Conclusion

I tried to present a comprehensive set of methods for reading files in Coffee, both text and binary. We looked at fifteen different ways of reading files in Java and nosotros ran functioning tests to run across which methods are the fastest.

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