Java provides several ways to read the content of a file. We'll explore a few common methods, from using the classic Scanner to the modern java.nio API.
java.util.ScannerThe Scanner class is a simple and effective way to parse text from a file. It can read a file line by line or token by token.
To use it, you create a Scanner object and pass a File object to its constructor.
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner;public class Main { public static void main(String[] args) { try { File myObj = new File("filename.txt"); Scanner myReader = new Scanner(myObj); while (myReader.hasNextLine()) { String data = myReader.nextLine(); System.out.println(data); } myReader.close(); } catch (FileNotFoundException e) { System.out.println("An error occurred: File not found."); e.printStackTrace(); } } }
java.io.BufferedReaderFor reading large files efficiently, BufferedReader is an excellent choice. It reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
It is often wrapped around a FileReader. Using try-with-resources is highly recommended.
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException;public class Main { public static void main(String[] args) { try (BufferedReader reader = new BufferedReader(new FileReader("filename.txt"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } } }
java.nio.file.Files (Modern Approach)For small to medium-sized files, the modern NIO.2 API provides a very convenient one-liner to read all lines of a file into a List of strings.
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List;public class Main { public static void main(String[] args) { try { List<String> allLines = Files.readAllLines(Paths.get("filename.txt")); for (String line : allLines) { System.out.println(line); } } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } } }
Warning: Be careful using
Files.readAllLines()on very large files, as it will attempt to load the entire file content into memory, which could lead to anOutOfMemoryError. For large files, theBufferedReaderapproach is safer.
Files.readString()Introduced in Java 11, the Files.readString() method provides an incredibly simple way to read the entire contents of a file into a single String. This is perfect for smaller files where you need all the text at once.
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths;public class Main { public static void main(String[] args) { Path path = Paths.get("filename.txt"); try { // Reads the entire file into memory as a String String content = Files.readString(path); System.out.println("File Content:\n" + content); } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } } }
Files.lines() (Streams)In the previous section, we warned that Files.readAllLines() can cause memory issues with large files. A more modern and memory-efficient alternative is Files.lines().
This method returns a Stream<String>. Instead of loading the entire file into memory at once, it lazily populates the stream as it is consumed. This makes it ideal for processing massive files efficiently.
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream;public class Main { public static void main(String[] args) { Path path = Paths.get("large-file.txt"); // The try-with-resources block ensures the stream (and underlying file) is closed try (Stream<String> lines = Files.lines(path)) { // Process lines using the Stream API (e.g., filter and print) lines.filter(line -> line.contains("ERROR")) .forEach(System.out::println); } catch (IOException e) { System.err.println("Error reading file: " + e.getMessage()); } } }
Which modern method should you use to memory-efficiently read a massive file line by line?