1

Any groovy way to read a file backwards? Took a look at Reader class, but nothing there seems to help. My use case is mostly finding the last line of a file that matches a condition (regex, contains a string etc.).

Later Edit:

I think this question is not really a duplicate of the tail one. I see tail as more of a 'live' processing of a file. My problem is more into processing big log files (size in tens of GB), so loading whole file into memory is not an option. The file content is static (not updated during processing).

For example, each time an object is updated we log a line saying which user did it and at some later point we need to the last user that generated that update.

Thanks

user4132657
  • 207
  • 1
  • 3
  • 10
  • 1
    This is not really groovy specific. You can take a look at http://stackoverflow.com/questions/6011345/read-a-file-line-by-line-in-reverse-order, http://stackoverflow.com/questions/8664705/how-to-read-file-from-end-to-start-in-reverse-order-in-java and probably many more. – Artur Biesiadowski Feb 14 '17 at 14:50
  • I agree that the problem itself is not groovy specific, but I'm trying to see if there is some elegant groovy solution to it. – user4132657 Feb 14 '17 at 14:52
  • Do you mind posting more details with relevant information such as sample data? – Rao Feb 14 '17 at 15:25
  • I would tend to agree that this is not a direct duplicate. I don't have a pure groovy solution, but I have a potential solution using groovy metaprogramming. Unfortunately I am unable to add it since this question has been closed as duplicate. Could somebody consider re-opening this question? – Matias Bjarland Feb 15 '17 at 11:18
  • 1
    As this thread is closed I added [a gist with a potential solution](https://gist.github.com/mbjarland/bc85071f5e8bc4ce1e5368388ae757ef). It does use an external dependency, but on the upside it does not read the entire file into memory and it does use groovy style idioms. It adds a `file.findLineReverse { String line -> ... }` method to the File class using groovy meta programming. – Matias Bjarland Feb 15 '17 at 11:37
  • I timed the above method on a 30G text file looking for the 10th last line. Took 5ms on my workstation which feels good enough to me. The gist uses commons-io ReverseLinesFileReader under the hood. – Matias Bjarland Feb 15 '17 at 11:58

2 Answers2

0

This worked for me:

String filePath = '/path/to/file'
File file = new File(filePath)
String sample = 'searchSample'

file.text.split('\n').reverse().find {it.contains(sample)}

UPD

Also maybe FileUtils#backWardsRead() will be helpful for you.

Anton Hlinisty
  • 1,441
  • 1
  • 20
  • 35
  • Loading the full file content in memory in not possible due to file size. I assume the FileUtils#backWardsRead is the one from [here](http://stackoverflow.com/questions/6011345/read-a-file-line-by-line-in-reverse-order). That looks interesting, thanks. – user4132657 Feb 15 '17 at 07:55
0

This doesn't read the file backwards, but it does process the lines backwards, which I believe lines up with the intended use case of finding the "last line in the file that matches a condition."

import java.util.stream.Collectors
new File('myfile.csv').newReader()
                      .lines()
                      .collect(Collectors.toList())
                      .reverse()
                      .find { line -> line ==~ myRegex }

This requires Java 8 as it uses the Stream API.

bdkosher
  • 5,753
  • 2
  • 33
  • 40