2016-03-16 20 views
10

Per il mio progetto ho bisogno di scaricare un file zip da un server FTP, che rilascia un nuovo zip circa 13 volte l'anno. Ho bisogno di scaricare l'ultimo file seguente convenzione del server di denominazione:
Prefix + release number (one or two digits) + year (two digits) + suffix + ".zip"Ordinamento di un array di nomi di file contenenti stringhe con numeri

per esempio: ALFP1016F.zip

Il prefisso sarà sempre lo stesso (ALFP) ed il suffisso F o P (sta per " pieno "o" parziale "; ho bisogno solo dei file che terminano con il suffisso F). Oltre a ciò, ci sono molti altri file nella directory che devo ignorare perché hanno prefissi diversi. Quindi, ho bisogno di ottenere il file più recente nella matrice seguendo questo ordine di priorità:

  1. L'anno più recente. Ovviamente il '99 non dovrebbe essere considerato l'anno più recente.
  2. più recente numero di release

Per esempio, se ho questo elenco di nomi di file (full server directory):

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

mio risultato atteso sarebbe
ALFP716F.zipperché 16 è l'anno più recente e 7 il numero di rilascio più recente di quell'anno

.

Ecco che cosa ho fatto finora:

//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(); } 
} 

Ho fatto un tentativo misero a scrivere il metodo returnMostRecent(String[]), ma abbiamo finito con un pasticcio incomprensibile non vale la pena di essere pubblicati qui.

Come è possibile ordinare questo array e restituire in modo efficace il file più recente in seguito al mio ordine di priorità?

+1

È possibile usare [espressioni regolari con Cattura di gruppi] (https://docs.oracle.com/javase/tutorial/essential/regex/groups.html) per isolare le parti importanti dei nomi dei file e quindi usarli per trovare la versione più recente (non è necessario ordinarli effettivamente). Se questo è troppo complicato, usa più 'substring()' per fare lo stesso. –

risposta

3

Non ho provato questo, ma penso che dovrebbe funzionare.

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; 
} 
+0

Questo sembra fare il trucco, a condizione che il numero di versione sia sempre di una cifra, il che non è il caso. – justbourv

+0

Ho aggiunto due righe due al codice. Questo dovrebbe prendersene cura. – Till

+0

Ho dovuto modificare un po 'il codice, ma alla fine ho funzionato. Grazie! – justbourv

1

È possibile utilizzare espressioni regolari e fare qualcosa di simile per analizzare tutto l'anno e la versione:

public static void main(String[] args) 
{ 
    int year = -1; 
    int version = -1; 
    String test = "ALFP716F.zip"; 
    if(test.matches("ALFP\\d+F.zip")) 
    { 
     Pattern pattern = Pattern.compile("\\d+"); 
     Matcher matcher = pattern.matcher(test); 
     matcher.find(); 
     String tempString = matcher.group(0); 
     year = Integer.parseInt(tempString.substring((tempString.length() - 2))); 
     version = Integer.parseInt(tempString.substring(0, (tempString.length() - 2))); 
    } 
    System.out.println("Year: " + year + " Version: " + version); 

} 
5

Se si utilizza Java8 si può fare:

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

dove comparatore stampa è basato sull'estrazione numeri dal nome del file e confrontandoli

+0

presuppone che il numero di versione sia una sola cifra, dove come risposta brso05 non è –

+0

@BalajiKrishnan che è vero, è necessario un comparatore personalizzato per ordinare correttamente i numeri. Lo lascio in OP poiché brso05 ha già dato un suggerimento – AdamSkywalker

+0

'Stream.max' sarebbe più efficiente e probabilmente più chiaro di concatenare' sorted' e 'findFirst'. Inoltre, se non hai intenzione di fornire un comparatore funzionante, dovresti probabilmente scrivere qualcosa come "appropriateComparator" invece di "Comparator.reverseOrder()", quindi è almeno chiaro che "Comparator.reverseOrder()" non funzionerà. – user2357112

2

Io suggerisco questo approccio:

final String[] filesArr = { "1stpage712.txt", "1stpage712.pdf", "1stpage914.pdf", "ALFP1015F.zip", "ALFP1015P.zip", "ALFP716F.zip", 
      "ALFP716P.zip", "FSFP816F.zip", "FSFP816P.zip" }; 

    // turn the array into a list. 
    final List<String> filesList = new ArrayList<String>(); 
    // add to the list only the good candidates 
    for (int i = 0; i < filesArr.length; i++) { 
     if (filesArr[i].matches("ALFP\\d+F.zip")) { 
      System.out.println("candidate"); 
      filesList.add(filesArr[i]); 
     } 
    } 
    System.out.println(filesList); 
    Collections.sort(filesList, new Comparator<String>() { 

     @Override 
     public int compare(String o1, String o2) { 
      final SimpleDateFormat df = new SimpleDateFormat("mmyy"); 
      // get the date of the file 
      final String dat1 = o1.substring(o1.indexOf("ALFP"), o1.indexOf("ALFP") + 3); 
      final String dat2 = o2.substring(o2.indexOf("ALFP"), o2.indexOf("ALFP") + 3); 
      Date date1; 
      Date date2; 
      try { 
       date1 = df.parse(dat1); 
       date2 = df.parse(dat2); 

       return date1.compareTo(date2); 
      } catch (final ParseException e) { 
       System.out.println("Error parsing date.."); 
       return 0; 
      } 
     } 
    }); 

    // since the sort is made by date chronologically, the 1st element is the oldest and the last element is 
    // the newest 
    System.out.println("The file is: " + filesList.get(filesList.size() - 1)); 

} 
2

Io suggerisco questo Soluzione:

private static String returnMostRecent(String[] fileNames) 
    { 
     int lastTwoDigits = Calendar.getInstance().get(Calendar.YEAR) % 100; 
     int fullFileRel = 0; 
     int partialFileRel = 0; 
     for(String myStr : fileNames) 
     { 

      if(myStr.startsWith("ALFP")) 
      { 
       System.out.println(myStr); 
      if(myStr.endsWith(""+lastTwoDigits+"F.zip")) 
      { 
       String temp = myStr.substring(4,myStr.length()-7); 
       System.out.println("temp : "+temp); 
       int releaseNum = Integer.parseInt(temp); 
       System.out.println("releaseNum : "+releaseNum); 
       if(releaseNum > fullFileRel) 
        fullFileRel = releaseNum;    
      } 

      if(myStr.endsWith(""+lastTwoDigits+"P.zip")) 
      { 
       String temp = myStr.substring(4,myStr.length()-7); 
       System.out.println("temp : "+temp); 
       int releaseNum = Integer.parseInt(temp); 
       System.out.println("releaseNum : "+releaseNum); 
       if(releaseNum > fullFileRel) 
        partialFileRel = releaseNum; 
      }   
      } 
     } 

     System.out.println("full Rel :"+fullFileRel); 
     System.out.println("partial Rel :"+partialFileRel); 

     if(fullFileRel > partialFileRel) 
      return "ALFP"+fullFileRel+""+lastTwoDigits+"F.zip"; 
     else 
      return "ALFP"+partialFileRel+""+lastTwoDigits+"P.zip"; 
    } 
Problemi correlati