Reputation: 5419
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
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
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