Java IO Tutorial

How to read a file in Java

This article focus on a few of the commonly used methods to read a file in Java.

  1. Files.lines, return a Stream (Java 8)
  2. Files.readString, returns a String (Java 11), max file size 2G.
  3. Files.readAllBytes, returns a byte[] (Java 7), max file size 2G.
  4. Files.readAllLines, returns a List<String> (Java 8)
  5. BufferedReader, a classic old friend (Java 1.1 -> forever)
  6. 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.

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

Terminal

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.

ReadFile2.java

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.

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

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.

ReadFile4.java

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.

ReadFile5a.java

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.

ReadFile5b.java

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.

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.

ReadFile5c.java

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.

ReadFile6.java

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

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
1 Comment
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Carol
5 years ago

Thanks!