I’m viewing a log of file names and the times they were last modified in a specified day. Its contents look like:
(comment:file_02389.txt,lastmodified:Wed Oct 10 19:10:49)
(comment:file_02342.txt,lastmodified:Wed Oct 10 17:16:08)
(comment:file_02315.txt,lastmodified:Wed Oct 10 18:45:12)
(comment:file_02344.txt,lastmodified:Wed Oct 10 08:31:01)
The log is given as a single String with no line breaks. I want to parse the String to find the file which was most recently modified, i.e., has the latest date so file_02389.txt in this case. The character length of each “comment” is constant though hypothetically could change in the future and the file names won’t be unique if the same file is modified more than once.
Is there a most extensible/maintainable way of finding the most recent file? Execution time and memory aren't are as important factors. The main concern is that a beginner programmer can understand and work with the code.
My first thought was to split the String into a List that can be sorted with a custom Comparator. I consider this to be simple but not extensible:
{//given String log
...
//setup
List<String> temp = Arrays.asList(log.trim().split("\\(comment\\:")); //too complex for one line?
//the first entry is blank so it must be removed else a substring() call will fail
if(temp.get(0).equals(""))
temp.remove(0);
int period = full.get(0).indexOf('.');
int colon = full.get(0).indexOf(':');
//process
Collections.sort(temp, DATE);
return test.get(test.size()-1).substring(0, period)) //last entry is the most recent
}
public final Comparator<String> DATE = new Comparator<String>()
{
public int compare(String s1, String s2)
{
return s1.substring(28).compareTo(s2.substring(28));
}
};
It works but uses substrings that depend on the line length and a Comparator that is only useful in this single case. I dislike the use of .split and then having to remove the first entry but I want to avoid a true and hard to understand regex if that is an alternative. Treating the dates as Strings instead of comparing as Integers or date objects seems undesirable but saves lines of code.
I currently use a sorted map that avoids creating a single-use Comparator with a random-looking number but a specialized map seems rather complex for what I’m trying to do. I still think it’s better than creating one array for the file names, another for the times, then a third to copy the times so the times array can be sorted and its last value compared with the corresponding index in the copy.
{
...
//same setup as before
//process
//key is time, value is file name
SortedMap<String, String> map = new TreeMap<String, String>();
for(String s : temp)
map.put(s.substring(colon+1), s.substring(0, period));
//the value to which the last key is mapped is guaranteed to be the most recent file
return map.get(map.lastKey()); //too complex for one line?
}
Would something like this work? Basically parsing the date out of each line, building a collection of "Pair" objects so I can then sort the collection based on the Date.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class Parse {
/**
* @param args
* @throws ParseException
*/
public static void main(String[] args) throws ParseException {
StringBuilder sb = new StringBuilder();
sb.append("(comment:file_02389.txt,lastmodified:Wed Oct 10 19:10:49)").append("\n");
sb.append("(comment:file_02342.txt,lastmodified:Wed Oct 10 17:16:08)").append("\n");
sb.append("(comment:file_02315.txt,lastmodified:Wed Oct 10 18:45:12)").append("\n");
sb.append("(comment:file_02344.txt,lastmodified:Wed Oct 10 08:31:01)").append("\n");
//create a date format that can parse dates formatted in the file
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss");
//read the file into an array of lines (or read one line at a time)
String[] lines = sb.toString().split("\n");
//create an array of pair objects to hold the line as well as the date
List<Pair> list = new ArrayList<Pair>();
for(int i=0;i<lines.length;i++){
//get the date component of the line
String dateString = lines[i].substring(lines[i].length()-20, lines[i].length()-1);
Pair pair = new Pair();
pair.date = sdf.parse(dateString);
pair.line = lines[i];
list.add(pair);
}
Collections.sort(list);
System.out.println(list.get(list.size()-1).line);
}
}
class Pair implements Comparable<Pair>{
public Date date;
public String line;
@Override
public int compareTo(Pair o) {
return date.compareTo(o.date);
}
}