Core Java

Read Last N Lines From File in Java

Reading the last N lines of a file is a common task in Java, especially when dealing with log files or other large files where only the most recent entries are of interest. Java provides multiple ways to accomplish this task, ranging from standard libraries to third-party utilities. Let us delve to explore four methods to read the last N lines from a file in Java using BufferedReader, Scanner, NIO2 Files, and Apache Commons IO.

1. Using BufferedReader

The BufferedReader class in Java can be used to efficiently read text from an input stream. Here’s how you can use it to read the last N lines from a file.

1.1 Code Example and Output

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.LinkedList;
import java.util.List;

public class ReadLastNLinesUsingBufferedReader {
    public static List<String> readLastNLines(String filePath, int n) throws Exception {
        LinkedList<String> lines = new LinkedList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
                if (lines.size() > n) {
                    lines.removeFirst();
                }
            }
        }
        return lines;
    }

    public static void main(String[] args) throws Exception {
        List<String> lastNLines = readLastNLines("example.txt", 5);
        for (String line : lastNLines) {
            System.out.println(line);
        }
    }
}

The code reads a file line by line using BufferedReader. We use a LinkedList<String> to store the last N lines. As we read each line, we add it to the list, and if the list exceeds N lines, we remove the first line. This way, the list always contains only the last N lines.

If we want the last 5 lines, the output will be:

Line 4
Line 5
Line 6
Line 7
Line 8

2. Using Scanner

The Scanner class in Java is often used to parse primitive types and strings using regular expressions. It can also be used to read the last N lines of a file.

2.1 Code Example and Output

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class ReadLastNLinesUsingScanner {
    public static List<String> readLastNLines(String filePath, int n) throws Exception {
        LinkedList<String> lines = new LinkedList<>();
        try (Scanner scanner = new Scanner(new File(filePath))) {
            while (scanner.hasNextLine()) {
                lines.add(scanner.nextLine());
                if (lines.size() > n) {
                    lines.removeFirst();
                }
            }
        }
        return lines;
    }

    public static void main(String[] args) throws Exception {
        List<String> lastNLines = readLastNLines("example.txt", 5);
        for (String line : lastNLines) {
            System.out.println(line);
        }
    }
}

This approach is similar to the BufferedReader method. The Scanner reads the file line by line, and we store the last N lines in a LinkedList<String>. When the size of the list exceeds N, we remove the first element, ensuring that only the last N lines are retained.

If we want the last 5 lines, the output will be:

Line 4
Line 5
Line 6
Line 7
Line 8

3. Using NIO2 Files

The NIO2 API, introduced in Java 7, offers the Files class, which provides a lot of utility methods for file operations.

3.1 Code Example and Output

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class ReadLastNLinesUsingNIO2Files {
    public static List<String> readLastNLines(String filePath, int n) throws Exception {
        Path path = Paths.get(filePath);
        List<String> allLines = Files.readAllLines(path);
        return allLines.subList(Math.max(allLines.size() - n, 0), allLines.size());
    }

    public static void main(String[] args) throws Exception {
        List<String> lastNLines = readLastNLines("example.txt", 5);
        for (String line : lastNLines) {
            System.out.println(line);
        }
    }
}

The Files.readAllLines() method reads all lines from a file into a list. We then use subList() to get the last N lines. This approach may be less memory efficient for large files since it reads all lines into memory at once.

If we want the last 5 lines, the output will be:

Line 4
Line 5
Line 6
Line 7
Line 8

4. Using Apache Commons IO

The Apache Commons IO library provides utility methods for file operations. The FileUtils class makes it easy to read the last N lines from a file.

4.1 Code Example and Output

import org.apache.commons.io.input.ReversedLinesFileReader;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class ReadLastNLinesUsingApacheCommonsIO {
    public static List<String> readLastNLines(String filePath, int n) throws Exception {
        List<String> result = new ArrayList<>();
        try (ReversedLinesFileReader reader = new ReversedLinesFileReader(new File(filePath), StandardCharsets.UTF_8)) {
            for (int i = 0; i < n; i++) {
                String line = reader.readLine();
                if (line == null) break;
                result.add(0, line);
            }
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        List<String> lastNLines = readLastNLines("example.txt", 5);
        for (String line : lastNLines) {
            System.out.println(line);
        }
    }
}

The ReversedLinesFileReader reads lines from a file in reverse order, which is ideal for fetching the last N lines. We use a loop to read the last N lines and add them to a list. The result is then returned in the correct order.

If we want the last 5 lines, the output will be:

Line 4
Line 5
Line 6
Line 7
Line 8

5. Conclusion

Reading the last N lines of a file in Java can be done in several ways, depending on the specific use case and the size of the file. The BufferedReader and Scanner methods are straightforward and work well for most cases. The NIO2 Files method is useful but may not be memory efficient for large files. The Apache Commons IO method is very efficient and easy to implement, especially for large files. Choose the approach that best fits your needs.

5.1 Comparison of Methods to Read Last N Lines From File in Java

MethodCode ComplexityMemory EfficiencyPerformanceCode Example
BufferedReaderModerateHigh (memory efficient for moderate sizes)Good (linear time complexity)BufferedReader reads line by line and maintains a queue of last N lines.
ScannerModerateHigh (similar to BufferedReader)Good (similar to BufferedReader)Scanner also reads line by line and maintains a queue of last N lines.
NIO2 FilesSimpleLow (reads all lines into memory)Potentially slow for large files (linear time but reads entire file)Files.readAllLines reads the entire file into memory, then extracts the last N lines.
Apache Commons IOSimpleHigh (efficient for large files)Excellent (reads lines in reverse order)ReversedLinesFileReader reads lines from the end of the file, which is efficient for large files.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button