Thursday, 11 February 2016

How to read file from the last line in Java

There are applications where you have to read huge files line by line may be using some tool like Pentaho, Camel. Let's say these files are in the format header, records and footer and you need to check something in the footer (last line of the file) and if that condition is not met you need to reject the file. Now, reading line by line in such scenario, will be wasteful as you'll anyway reject the file in the end.

So for such scenarios it is better to read the last line (or may be last N lines) to have better throughput. In this post you will see how to read a file from the last line in Java.

In Java it can be done using RandomAccessFile which has a seek method to set the file-pointer offset, measured from the beginning of the file.

Apache Commons IO also has a ReversedLinesFileReader class which reads lines in a file reversely.

Example code using RandomAccessFile

Let's say you have a file aa.txt which has the following content -

This is the first line.
This is the second line.
This is the third line.
This is the fourth line.
And you want to read last line of this file.
public class ReadFileLast {

 public static void main(String[] args) {
  ReadFileLast rf = new ReadFileLast();
  File file = new File("F:\\NetJS\\test\\aa.txt");
  // calling method
  rf.readFromLast(file);
  //rf.reverseLines(file);

 }
 
 // Read last line of the file
 public void readFromLast(File file){
  
        int lines = 0;
        StringBuilder builder = new StringBuilder();
        RandomAccessFile randomAccessFile = null;
        try {
         randomAccessFile = new RandomAccessFile(file, "r");
         long fileLength = file.length() - 1;
         // Set the pointer at the last of the file
         randomAccessFile.seek(fileLength);
         for(long pointer = fileLength; pointer >= 0; pointer--){
           randomAccessFile.seek(pointer);
           char c;
           // read from the last one char at the time
           c = (char)randomAccessFile.read(); 
           // break when end of the line
           if(c == '\n'){
              break;
           }
           builder.append(c);
         }
         // Since line is read from the last so it 
         // is in reverse so use reverse method to make it right
         builder.reverse();
         System.out.println("Line - " + builder.toString());
        } catch (FileNotFoundException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
        catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }finally{
           if(randomAccessFile != null){
              try {
                 randomAccessFile.close();
              } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
              }
           }
       }
  }
}

Output

Line - This is the fourth line.

Here you get the file length and then using the seek method move the pointer to that point (end of the file). From there you start reading backward char by char. Since you are reading in reverse so you need to use reverse method of the StringBuilder to make the String straight.

If you want to read n last lines of the file you can use the following method.

       // Read n lines from the end of the file
 public void readFromLast(File file, int lines){
  int readLines = 0;
        StringBuilder builder = new StringBuilder();
        RandomAccessFile randomAccessFile = null;
        try {
          randomAccessFile = new RandomAccessFile(file, "r");
          long fileLength = file.length() - 1;
          // Set the pointer at the last of the file
          randomAccessFile.seek(fileLength);
          for(long pointer = fileLength; pointer >= 0; pointer--){
            randomAccessFile.seek(pointer);
            char c;
            // read from the last one char at the time
            c = (char)randomAccessFile.read(); 
            // break when end of the line
            if(c == '\n'){
              readLines++;
              if(readLines == lines)
               break;
            }
            builder.append(c);
          }
          // Since line is read from the last so it 
          // is in reverse so use reverse method to make it right
          builder.reverse();
          System.out.println("Line - " + builder.toString());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }finally{
          if(randomAccessFile != null){
             try {
                randomAccessFile.close();
             } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
             }
        }
   }
}

Using Apache Commons IO

public class ReadFileLast {

 public static void main(String[] args) {
  ReadFileLast rf = new ReadFileLast();
  File file = new File("F:\\NetJS\\test\\aa.txt");
  // calling method
  rf.reverseLines(file);

 }
 
// Reading file from the last using
// using ReversedLinesFileReader
public void reverseLines(File file){
 ReversedLinesFileReader object = null;
 try {
  object = new ReversedLinesFileReader(file);
  System.out.println("Line - " + object.readLine());
 } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }finally{
  try {
   object.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}
}

That's all for this topic How to read file from the last line. If you have any doubt or any suggestions to make please drop a comment. Thanks!


You may also like -

>>>Go to Java Programs page

2 comments:

  1. Thank you so much for this great explanation. Through the first method I can read the last line of the file, however, is there any way to get the first character of the last line once it reads the line?

    For instance as we get the output:
    Line - This is the fourth line

    I want to get also the first string "This" in the line and print it out.

    Thanks in advanced






    ReplyDelete