Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an array of filenames containing strings with numbers

For my project I need to download a zip file from an FTP server, which releases a new zip about 13 times a year. I need to download the latest file following the server's naming convention:
Prefix + release number (one or two digits) + year (two digits) + suffix + ".zip"

for instance: ALFP1016F.zip

The prefix will always be the same (ALFP) and the suffix either F or P (stands for "full" or "partial"; I need only the files ending with suffix F). On top of that, there are several other files in the directory I need to ignore because they have different prefixes. Then, I need to get the most recent file in the array following this priority order:

  1. Most recent year. Of course '99 should not be seen as the most recent year.
  2. Most recent release number

For instance, if I have this listing of filenames (full server directory):

1stpage712.pdf
1stpage914.pdf
ALFP1015F.zip
ALFP1015P.zip
ALFP716F.zip
ALFP716P.zip
FSFP816F.zip
FSFP816P.zip

My expected output would be
ALFP716F.zip because 16 is the most recent year, and 7 the most recent release number from that year

.

Here's what I've done so far:

//necessary imports
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

//initialize FTP client
ftpClient = new FTPClient();

try {
    //connect to server
    ftpClient.connect(server, port);
    ftpClient.login(username, password);
    ftpClient.enterLocalPassiveMode();
    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

    //list all names from server
    String[] filenames = ftpClient.listNames();

    //return expected file name
    String expectedFileName = returnMostRecent(filenames);
} catch (Exception e) { 
    e.printStackTrace(); 
} finally {
    try {
        if (ftpClient.isConnected()) {
            ftpClient.logout();
            ftpClient.disconnect();
            System.out.println("Disconnected from server");
        }
    } catch (IOException ex) { ex.printStackTrace(); }
}

I have done a miserable attempt at writing the returnMostRecent(String[]) method, but ended up with an unintelligible mess not worth being posted here.

How can I sort this array and effectively return the most recent file following my priority order?

like image 211
justbourv Avatar asked Mar 16 '16 15:03

justbourv


2 Answers

If you use Java8 you can do:

String file = Arrays.stream(filenames)
                    .filter(s -> s.startsWith("ALFP") && s.endsWith("F.zip"))
                    .max(getReleaseComparator())                        
                    .orElse(null);

where release comparator is based on extracting numbers from file name and comparing them

like image 137
AdamSkywalker Avatar answered Oct 24 '22 03:10

AdamSkywalker


I haven't tested this but I think it should work.

private String returnMostRecent(String[] fileNames) {
   String file = null;
   double version = -1;
   for(String name : listNames)
   {
      // skip files that don't match
      if (!name.matches("ALFP[0-9]*F.zip"))
          continue;
      // get digits only
      String digits = name.replaceAll("\\D+","");
      // format digits to <year>.<version>
      String vstr = digits.substring(digits.length-2,digits.length()) + ".";
      if (digits.length() < 4)
         vstr += "0";
      vstr = digits.substring(0, digits.length()-2);
      double v = Double.parseDouble(vstr);
      if (v > version)
      {
          version = v;
          file = name;
      }
   }

   return file;
}
like image 39
Till Avatar answered Oct 24 '22 02:10

Till