How to read a file in Java
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.lines
for Stream and parallel features or the classic BufferedReader
.
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.
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.
package com.mkyong.io.file;
import com.mkyong.io.utils.ResourceHelper;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class ReadFile1 {
public static void main(String[] args) throws IOException {
String fileName = ResourceHelper.getAbsoluteFilePath("app.log");
// auto-close the resources
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/mkyong/large.txt";
Stream<String> lines = Files.lines(Paths.get(fileName));
// parallel
lines.parallel().forEach(l -> {/* do work */});
1.4 A common mistake is to convert a large Stream
into a List
directly, and it will throw java.lang.OutOfMemoryError: Java heap space
if the Stream size is larger than the running JVM heap size.
// a large text file, for example, 10G
String fileName = "/home/mkyong/large.txt";
Stream<String> lines = Files.lines(Paths.get(fileName));
// java.lang.OutOfMemoryError: Java heap space
List<String> collect = lines.collect(Collectors.toList());
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
.
package com.mkyong.io.file;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ReadFile2 {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/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.
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
.
import com.mkyong.io.utils.ResourceHelper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ReadFile3 {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/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
.
package com.mkyong.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;
public class ReadFile4 {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/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.
package com.mkyong.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile5a {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/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.
package com.mkyong.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile5b {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/app.log";
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
.
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.
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.
package com.mkyong.io.file;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ReadFile5c {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/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 (IOException 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
.
package com.mkyong.io.file;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class ReadFile6 {
public static void main(String[] args) throws IOException {
String fileName = "/home/mkyong/app.log";
try (Scanner sc = new Scanner(new FileReader(fileName))) {
while (sc.hasNextLine()) {
String line = sc.nextLine();
}
}
}
}
Download Source Code
$ git clone https://github.com/mkyong/core-java
$ cd java-io
Thanks!