This article focus on a few of the commonly used methods to read a file in Java.
Files.lines, return aStream(Java 8)Files.readString, returns aString(Java 11), max file size 2G.Files.readAllBytes, returns abyte[](Java 7), max file size 2G.Files.readAllLines, returns aList<String>(Java 8)BufferedReader, a classic old friend (Java 1.1 -> forever)Scanner(Java 1.5)
The new Java 8 Files.lines is working well in reading small or large text files, returns a Stream (flexible type and support parallel), auto-close the resources, and has a single line of clean code.
Stream<String> lines = Files.lines(Paths.get(fileName));
In modern Java 8+, we should use Files.lines to read a text file.
Note
In a nutshell, there is not much difference in reading in small files, just the taste of the return type. For reading in a large file, picks Java 8
Files.linesfor Stream and parallel features or the classicBufferedReader.
A Text File
Here’s a simple text file, contains only five lines. The rest of the Java examples are going to read this file.
src/main/resources/app.log
Line 1
Line 2
Line 3
Line 4
Line 5
1. Files.lines (Java 8)
1.1 This example uses the Java 8 Files.lines to read the above file into a Stream, and print it line by line. Furthermore, the Files.lines will helps to auto-close the opened resource (file); we do not need to wrap the code with try-with-resources.
ReadFile1.java
package com.favtuts.io.file;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile1 {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
// auto-close the resoures
Stream<String> lines = Files.lines(Paths.get(fileName));
// does not preserve order
lines.forEach(System.out::println);
// preserve order
// lines.forEachOrdered(System.out::println);
}
}
Output
Line 1
Line 2
Line 3
Line 4
Line 5
1.2 For reading in a small text file, we can use collect convert the Stream into a List<String> easily.
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
Stream<String> lines = Files.lines(Paths.get(fileName));
// only for small text file
List<String> collect = lines.collect(Collectors.toList());
1.3 For reading in a large text file, and if the order of the line does not matter, we can turn on the Stream’s parallel feature to further improve reading speed.
// a large text file, for example, 10G
String fileName = "/home/favtuts/large.txt";
Stream<String> lines = Files.lines(Paths.get(fileName));
// parallel
lines.parallel().forEach(l -> {/* do work */});
1.5 The last one, the lines.forEach, does not preserve the order of the line, try lines.forEachOrdered if we want to maintain the order.
Stream<String> lines = Files.lines(Paths.get(fileName)); // does not preserve order lines.forEach(System.out::println); // preserve order lines.forEachOrdered(System.out::println);
2. Files.readString (Java 11)
2.1 This Files.readString() read a file into a string, and if the reading file size exceeds 2G, it will throws java.lang.OutOfMemoryError: Required array size too large.
ReadFile2.java
package com.favtuts.io.file;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ReadFile2 {
public static void main(String[] args) throws IOException {
String fileName = "/home/tvt/workspace/favtuts/large.txt";
// default UTF_8
String s = Files.readString(Paths.get(fileName));
System.out.println(s);
//String s = Files.readString(Paths.get(fileName), StandardCharsets.UTF_8);
}
}
2.2 Review the source code, the new Java 11 readString, internally use the existing Java 7 readAllBytes to read a file into a byte[] and JLA.newStringNoRepl to convert the byte[] back to a string.
Files.java
package java.nio.file;
public final class Files {
public static String readString(Path path, Charset cs) throws IOException {
Objects.requireNonNull(path);
Objects.requireNonNull(cs);
byte[] ba = readAllBytes(path);
if (path.getClass().getModule() != Object.class.getModule())
ba = ba.clone();
return JLA.newStringNoRepl(ba, cs);
}
//...
}
3. Files.readAllBytes (Java 7)
3.1 This example uses Files.readAllBytes to read a file into a byte arrays byte[], if the reading file size exceeds 2G, it will throws java.lang.OutOfMemoryError: Required array size too large.
ReadFile3.java
package com.favtuts.io.file;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile3 {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
byte[] bytes = Files.readAllBytes(Paths.get(fileName));
String content = new String(bytes, StandardCharsets.UTF_8);
System.out.println(content);
}
}
4. Files.readAllLines (Java 8)
4.1 This example uses Files.readAllLines to read a file into a List<String>, if the file size is larger than the running JVM heap size, it will throw java.lang.OutOfMemoryError: Java heap space.
ReadFile4.java
package com.favtuts.io.file;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile4 {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
List<String> lines = Files.readAllLines(Paths.get(fileName), StandardCharsets.UTF_8);
lines.forEach(System.out::println);
}
}
5. BufferedReader (Java 1.1)
5.1 A classic and old friend, BufferedReader example, works well in reading small and large files, and the default buffer size (8k) is large enough for most purposes.
ReadFile5a.java
package com.favtuts.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile5a {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
// defaultCharBufferSize = 8192; or 8k
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}
5.2 We can specify the buffer size.
ReadFile5b.java
package com.favtuts.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile5b {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
// defaultCharBufferSize = 8192; or 8k
int bufferSize = 10240; //10k
try (BufferedReader br = new BufferedReader(new FileReader(fileName), bufferSize)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}
5.3 In Java 8, we can use the new Files.newBufferedReader to create a BufferedReader.
ReadFile5c.java
package com.favtuts.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile5c {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}
Review the source code, nothing special.
Files.java
package java.nio.file;
public final class Files {
public static BufferedReader newBufferedReader(Path path, Charset cs)
throws IOException
{
CharsetDecoder decoder = cs.newDecoder();
Reader reader = new InputStreamReader(newInputStream(path), decoder);
return new BufferedReader(reader);
}
//
}
Read this – Java How to read file with BufferedReader
5.4 For self-reference, a classic try catch finally to close an opened file manually.
ReadFile5d.java
package com.favtuts.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile5d {
public static void main(String[] args) {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
BufferedReader br = null;
FileReader fr = null;
try {
fr = new FileReader(fileName);
br = new BufferedReader(fr);
// read line by line
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.format("IOException: %s%n", e);
} finally {
try {
if (br != null)
br.close();
if (fr != null)
fr.close();
} catch (Exception ex) {
System.err.format("IOException: %s%n", ex);
}
}
}
}
6. Scanner (Java 1.5)
6.1 In the Scanner class, the delimiter feature is still useful for reading and filtering a small file. Java 9 and Java 10 added new methods like findAll and constructors to improve the Scanner class. However, for reading in a large file, this Scanner class is slow compared to BufferedReader.
ReadFile6.java
package com.favtuts.io.file;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
import com.favtuts.io.utils.ResourceHelper;
public class ReadFile6 {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
try (Scanner sc = new Scanner(new FileReader(fileName))) {
while (sc.hasNextLine()) {
String line = sc.nextLine();
System.out.println(line);
}
}
}
}
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-io