Friday, July 23, 2021

10 Examples to read a text file in Java [UPDATED]

The Java IO API provides two kinds of interfaces for reading files, streams and readers. The streams are used to read binary data and readers to read character data. Since a text file is full of characters, you should be using a Reader implementations to read it. There are several ways to read a plain text file in Java e.g. you can use FileReader, BufferedReader or Scanner to read a text file. Every utility provides something special e.g. BufferedReader provides buffering of data for fast reading, and Scanner provides parsing ability. 

You can also use both BufferedReader and Scanner to read a text file line by line in Java. Then Java SE 8 introduces another Stream class java.util.stream.Stream which provides a lazy and more efficient way to read a file.

The JDK 7 also introduces a couple of nice utility e.g. Files class and try-with-resource construct which made reading a text file, even more, easier.

In this article, I am going to share a couple of examples of reading a text file in Java with their pros, cons, and important points about each approach. This will give you enough detail to choose the right tool for the job depending on the size of file, the content of the file, and how you want to read.



1. Reading a text file using FileReader

The FileReader is your general-purpose Reader implementation to read a file. It accepts a String path to file or a java.io.File instance to start reading. It also provides a couple of overloaded read() methods to read a character or read characters into an array or into a CharBuffer object. 

Here is an example of reading a text file using FileReader in Java:

public static void readTextFileUsingFileReader(String fileName) {
    try {
      FileReader textFileReader = new FileReader(fileName);
      char[] buffer = new char[8096];
      int numberOfCharsRead = textFileReader.read(buffer);
      while (numberOfCharsRead != -1) {
        System.out.println(String.valueOf(buffer, 0, numberOfCharsRead));
        numberOfCharsRead = textFileReader.read(buffer);
      }
      textFileReader.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

Output
Once upon a time, we wrote a program to read data from a text file.
The program failed to read a large file but then Java 8 come to
rescue, which made reading file lazily using Streams. 

You can see that instead of reading one character at a time, I am reading characters into an array. This is more efficient because read() will access the file several times but read(char[]) will access the file just one time to read the same amount of data.

I am using an 8KB of the buffer, so in one call I am limited to read that much data only. You can have a bigger or smaller buffer depending upon your heap memory and file size. You should also notice that I am looping until read(char[]) returns -1 which signals the end of the file.

Another interesting thing to note is to call to String.valueOf(buffer, 0, numberOfCharsRead), which is required because you might not have 8KB of data in the file or even with a bigger file, the last call may not be able to fill the char array and it could contain dirty data from the last read.





2. Reading a text file in Java using BufferedReader

The BufferedReader class is a Decorator which provides buffering functionality to FileReader or any other Reader. This class buffer input from source e.g. files into memory for the efficient read. In the case of BufferedReader, the call to read() doesn't always goes to file if it can find the data in the internal buffer of BufferedReader.

The default size of the internal buffer is 8KB which is good enough for most purpose, but you can also increase or decrease buffer size while creating BufferedReader object. The reading code is similar to the previous example.

public static void readTextFileUsingBufferdReader(String fileName) {
    try {
      FileReader textFileReader = new FileReader(fileName);
      BufferedReader bufReader = new BufferedReader(textFileReader);

      char[] buffer = new char[8096];

      int numberOfCharsRead = bufReader.read(buffer); // read will be from
      // memory
      while (numberOfCharsRead != -1) {
        System.out.println(String.valueOf(buffer, 0, numberOfCharsRead));
        numberOfCharsRead = textFileReader.read(buffer);
      }

      bufReader.close();

    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

Output
[From File] Java provides several ways to read file

In this example as well, I am reading the content of the file into an array. Instead of reading one character at a time, this is more efficient. The only difference between the previous examples and this one is that the read() method of BufferedReader is faster than the read() method of FileReader because read can happen from memory itself.

In order to read the full-text file, you loop until read(char[]) method returns -1, which signals the end of the file. See Core Java Volume 1 - Fundamentals to learn more about how BufferedReader class works in Java.

How to read a text file in Java




3. Reading a text file in Java using Scanner

The third tool or class to read a text file in Java is the Scanner, which was added on JDK 1.5 release. The other two FileReader and BufferedReader are present from JDK 1.0 and JDK 1.1 versions. The Scanner is a much more feature-rich and versatile class. 

It does not just provide reading but the parsing of data as well. You can not only read text data but you can also read the text as a number or float using nextInt() and nextFloat() methods.

The class uses regular expression pattern to determine token, which could be tricky for newcomers. The two main method to read text data from Scanner is next() and nextLine(), former one read words separated by space while later one can be used to read a text file line by line in Java. In most cases, you would use the nextLine() method as shown below:

public static void readTextFileUsingScanner(String fileName) {
    try {
      Scanner sc = new Scanner(new File(fileName));
      while (sc.hasNext()) {
        String str = sc.nextLine();
        System.out.println(str);
      }
      sc.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
Output
[From File] Java provides several ways to read the file.

You can use the hasNext() method to determine if there is any more token left to read in the file and loop until it returns false. Though you should remember that next() or nextLine() may block until data is available even if hasNext() return true. This code is reading the content of "file.txt" line by line. See this tutorial to learn more about the Scanner class and file reading in Java.




4. Reading a text file using Stream in Java 8

The JDK 8 release has brought some cool new features e.g. lambda expression and streams which make file reading even smoother in Java. Since streams are lazy, you can use them to read-only lines you want from the file e.g. you can read all non-empty lines by filtering empty lines. The use of method reference also makes the file reading code much more simple and concise, so much so that you can read a file in just one line as shown below:

Files.lines(Paths.get("newfile.txt")).forEach(System.out::println);

Output
This is the first line of file

something is better than nothing

this is the last line of the file

Now, if you want to do some pre-processing, here is code to trim each line, filter empty lines to only read non-empty ones, and remember, this is lazy because Files.lines() method return a stream of String and Streams are lazy in JDK 8 (see Java 8 in Action).

Files.lines(new File("newfile.txt").toPath())
.map(s -> s.trim()) 
.filter(s -> !s.isEmpty()) 
.forEach(System.out::println);


We'll use this code to read a file that contains a line that is full of whitespace and an empty line, the same one which we have used in the previous example, but this time, the output will not contain 5 line but just three lines because empty lines are already filtered, as shown below:

Output
This is the first line of file
something is better than nothing
this is the last line of the file

You can see only three out of five lines appeared because the other two got filtered. This is just the tip of the iceberg on what you can do with Java SE 8, See Java SE 8 for Really Impatient to learn more about Java 8 features.

Reading text file in Java 8 example



5. How to read a text file as String in Java

Sometimes you read the full content of a text file as String in Java. This is mostly the case with small text files as for large files you will face java.lang.OutOfMemoryError: java heap space error. Prior to Java 7, this requires a lot of boiler code because you need to use a BufferedReader to read a text file line by line and then add all those lines into a StringBuilder and finally return the String generated from that.

Now you don't need to do all that, you can use the Files.readAllBytes() method to read all bytes of the file in one shot. Once done that you can convert that byte array into String. as shown in the following example:

public static String readFileAsString(String fileName) {
    String data = "";
    try {
      data = new String(Files.readAllBytes(Paths.get("file.txt")));
    } catch (IOException e) {
      e.printStackTrace();
    }

    return data;
  }
Output
[From File] Java provides several ways to read file

This was a rather small file so it was pretty easy. Though, while using readAllBytes() you should remember character encoding. If your file is not in platform's default character encoding then you must specify the character doing explicitly both while reading and converting to String. Use the overloaded version of readAllBytes() which accepts character encoding. You can also see how I read XML as String in Java here.




6. Reading the whole file in a List

Similar to the last example, sometimes you need all lines of the text file into an ArrayList or Vector or simply on a List. Prior to Java 7, this task also involves boilerplate e.g. reading files line by line, adding them into a list, and finally returning the list to the caller, but after Java 7, it's very simple now. You just need to use the Files.readAllLines() method, which returns all lines of the text file into a List, as shown below:

public static List<String> readFileInList(String fileName) {
    List<String> lines = Collections.emptyList();
    try {
      lines = Files.readAllLines(Paths.get("file.txt"), StandardCharsets.UTF_8);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return lines;
}

Similar to the last example, you should specify character encoding if it's different from than platform's default encoding. You can use see I have specified UTF-8 here. Again, use this trick only if you know that file is small and you have enough memory to hold a List containing all lines of the text file, otherwise your Java program will crash with OutOfMemoryError.

10 Examples to read text file in Java



7. How to read a text file in Java into an array

This example is also very similar to the last two examples, this time, we are reading the contents of the file into a String array. I have used a shortcut here, first, I have read all the lines as List and then converted the list to an array. 

This results in simple and elegant code, but you can also read data into a character array as shown in the first example. Use the read(char[] data) method while reading data into a character array.

Here is an example of reading a text file into String array in Java:

public static String[] readFileIntoArray(String fileName) {
    List<String> list = readFileInList(fileName);
    return list.toArray(new String[list.size()]);
}

This method leverage our existing method which reads the file into a List and the code here is only to convert a list to an array in Java.



8. How to read a file line by line in Java

This is one of the interesting examples of reading a text file in Java. You often need file data as line by line. Fortunately, both BufferedReader and Scanner provide convenient utility method to read line by line. If you are using BufferedReader then you can use readLine() and if you are using Scanner then you can use nextLine() to read file contents line by line. In our example, I have used BufferedReader as shown below:

public static void readFileLineByLine(String fileName) {
    try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
      String line = br.readLine();
      while (line != null) {
        System.out.println(line);
        line = br.readLine();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

Just remember that A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a line feed.

How to read a file line by line in Java


Java Program to read a text file in Java

Here is the complete Java program to read a plain text file in Java. You can run this program in Eclipse provided you create the files used in this program e.g. "sample.txt", "file.txt", and "newfile.txt". Since I am using a relative path, you must ensure that files are in the classpath. If you are running this program in Eclipse, you can just create these files in the root of the project directory. The program will throw FileNotFoundException or NoSuchFileExcpetion if it is not able to find the files.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

/*
 * Java Program read a text file in multiple way.
 * This program demonstrate how you can use FileReader,
 * BufferedReader, and Scanner to read text file,
 * along with newer utility methods added in JDK 7
 * and 8. 
 */

public class FileReadingDemo {

  public static void main(String[] args) throws Exception {

    // Example 1 - reading a text file using FileReader in Java
    readTextFileUsingFileReader("sample.txt");
    
    // Example 2 - reading a text file in Java using BufferedReader
    readTextFileUsingBufferdReader("file.txt");
    
    // Example 3 - reading a text file in Java using Scanner
    readTextFileUsingScanner("file.txt");
    
    // Example 4 - reading a text file using Stream in Java 8
    Files.lines(Paths.get("newfile.txt")).forEach(System.out::println);    
    
    // Example 5 - filtering empty lines from a file in Java 8
    Files.lines(new File("newfile.txt").toPath())
    .map(s -> s.trim()) 
    .filter(s -> !s.isEmpty()) 
    .forEach(System.out::println);
    
    
    // Example 6 - reading a text file as String in Java
    readFileAsString("file.txt");
    
    
    // Example 7 - reading whole file in a List
    List<String> lines = readFileInList("newfile.txt");
    System.out.println("Total number of lines in file: " + lines.size());
    
    // Example 8 - how to read a text file in java into an array
    String[] arrayOfString = readFileIntoArray("newFile.txt");
    for(String line: arrayOfString){
    System.out.println(line);
    }
    
    // Example 9 - how to read a text file in java line by line
    readFileLineByLine("newFile.txt");
    
    // Example 10 - how to read a text file in java using eclipse
    // all examples you can run in Eclipse, there is nothing special about it. 
    
  }

  public static void readTextFileUsingFileReader(String fileName) {
    try {
      FileReader textFileReader = new FileReader(fileName);
      char[] buffer = new char[8096];
      int numberOfCharsRead = textFileReader.read(buffer);
      while (numberOfCharsRead != -1) {
        System.out.println(String.valueOf(buffer, 0, numberOfCharsRead));
        numberOfCharsRead = textFileReader.read(buffer);
      }
      textFileReader.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  public static void readTextFileUsingBufferdReader(String fileName) {
    try {
      FileReader textFileReader = new FileReader(fileName);
      BufferedReader bufReader = new BufferedReader(textFileReader);

      char[] buffer = new char[8096];

      int numberOfCharsRead = bufReader.read(buffer); // read will be from
      // memory
      while (numberOfCharsRead != -1) {
        System.out.println(String.valueOf(buffer, 0, numberOfCharsRead));
        numberOfCharsRead = textFileReader.read(buffer);
      }

      bufReader.close();

    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  public static void readTextFileUsingScanner(String fileName) {
    try {
      Scanner sc = new Scanner(new File(fileName));
      while (sc.hasNext()) {
        String str = sc.nextLine();
        System.out.println(str);
      }
      sc.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  public static String readFileAsString(String fileName) {
    String data = "";
    try {
      data = new String(Files.readAllBytes(Paths.get("file.txt")));
    } catch (IOException e) {
      e.printStackTrace();
    }

    return data;
  }

  public static List<String> readFileInList(String fileName) {
    List<String> lines = Collections.emptyList();
    try {
      lines = Files.readAllLines(Paths.get("file.txt"), StandardCharsets.UTF_8);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return lines;
  }

  public static String[] readFileIntoArray(String fileName) {
    List<String> list = readFileInList(fileName);
    return list.toArray(new String[list.size()]);

  }

  public static void readFileLineByLine(String fileName) {
    try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
      String line = br.readLine();
      while (line != null) {
        System.out.println(line);
        line = br.readLine();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

I have not printed the output here because we have already gone through that and discuss in respective examples, but you need Java 8 to compile and run this program. If you are running on Java 7, then just remove the example 4 and 5 which uses Java 8 syntax and features and the program should run fine.


That's all about how to read a text file in Java. We have looked at all major utilities and classes which you can use to read a file in Java like FileReader, BufferedReader, and Scanner. We have also looked at utility methods added on Java NIO 2 on JDK 7 like. Files.readAllLines() and Files.readAllBytes() to read the file in List and String respectively. 

Other Java File tutorials for beginners
  • How to check if a File is hidden in Java? (solution)
  • How to read an XML file in Java? (guide)
  • How to read an Excel file in Java? (guide)
  • How to read an XML file as String in Java? (example)
  • How to copy non-empty directories in Java? (example)
  • How to read/write from/to RandomAccessFile in Java? (tutorial)
  • How to append text to a File in Java? (solution)
  • How to read a ZIP file in Java? (tutorial)
  • How to read from a Memory Mapped file in Java? (example)

Finally, we have also touched new way of file reading with Java 8 Stream, which provides lazy reading and the useful pre-processing option to filter unnecessary lines.

No comments:

Post a Comment