Moonlit
Moonlit

Reputation: 5419

Read range of lines from Textfile

I have a pretty large the a textfile which looks like the following:

0  239.0 -13.0 0
1  240.0 -13.0 33
2  241.0 -13.0 34
3  242.0 -13.0 44
4  243.0 -13.0 45
5  244.0 -13.0 74
6  245.0 -13.0 74
7  246.0 -13.0 79
8  247.0 -13.0 79
9  248.0 -13.0 113
10  249.0 -13.0 113
11  250.0 -13.0 120
12  251.0 -13.0 120
13  252.0 -13.0 153
14  253.0 -13.0 153
15  254.0 -13.0 160
16  255.0 -13.0 160
17  256.0 -13.0 194
18  257.0 -13.0 195
19  258.0 -13.0 199
20  259.0 -13.0 200
21  260.0 -13.0 232
22  261.0 -13.0 232
23  262.0 -13.0 239
...
...

The last entry in each line is a timestamp. Now I want to implement a method called read(int timestamp, int range) which returns me a range of lines from this textfile in an efficient way. For example if I call read(10250,100) I want to seek to the line with timestamp 10250 (if such one exists, else the take nearest next) and return 100 lines before the timestamp line, the line with the timstamp itself and 100 lines after the timestamp line in a String array.

Here is my current implementation of read(int timestamp, int range):

public static void read(int timestamp,int range) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader("LOG_TEST"));
    String line;
    int currTimestamp;
    while ((line = br.readLine()) != null) {
        currTimestamp = Integer.parseInt(line.split("\\s+")[3]);
        if (currTimestamp >= timestamp) {
            for(int i = 0; i<range;i++){
                System.out.println(br.readLine());
            }
            break;
        }
    }
    br.close();
}

The problem is that this implementation only prints out the 100 lines after the timestamp. I don't know how to include the 100 lines before. Because I don't know in which line the timestamp line is I need somehow to read "backwards" to get the 100 lines before. How can I implement this in an efficient way? kind regards

Upvotes: 1

Views: 2125

Answers (2)

vefthym
vefthym

Reputation: 7462

I would use a CircularFifoQueue with fixed size range, e.g. 100. Quoting its add method:

Adds the given element to this queue. If the queue is full, the least recently added element is discarded so that a new element can be inserted.

This way, you only keep in memory range lines, and not all the previous ones.

You can download the jar from here.

It also provides a get(int index) method that you can use to print the lines in the order that you wish, but I don't think you need that, as the iterator returns the elements by insertion order. So, here is my suggestion:

public static void read(int timestamp,int range) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader("LOG_TEST"));
    String line;
    CircularFifoQueue<String> prevLines = new CircularFifoQueue<>(range);
    int currTimestamp;
    while ((line = br.readLine()) != null) {            
        currTimestamp = Integer.parseInt(line.split("\\s+")[3]);
        if (currTimestamp >= timestamp) {
            for (String prevLine : prevLines) {  //prints the range previous lines
                System.out.println(prevLine);
            }
            System.out.println(line);            //prints the current line
            for(int i = 0; i<range;i++){         //prints the following range lines
                System.out.println(br.readLine());
            }                
            break;
        } else {
            prevLines.add(line);
        }
    }
    br.close();
}

Upvotes: 1

gifpif
gifpif

Reputation: 4917

try:

public static void read(int timeStamp,int range) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader("LOG_TEST"));
    String line;
    ArrayList<String> save=new ArrayList<String>();
    int currTimestamp;
    String str:
    while ((line = br.readLine()) != null) {
        timestamp = Integer.parseInt(line.split("\\s+")[3]);
        save.add(br.readLine());
        int i=save.length-100;
        if (currTimestamp >= timestamp) {
            //logic for print 100 line from array save
            ...

            for(int i = 0; i<range;i++){
                System.out.println(br.readLine());
            }
            break;
        }
    }
    br.close();
}

Upvotes: 0

Related Questions