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 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