Ordenar una matriz de nombres de archivo que contienen cadenas con números

Para mi proyecto tengo que descargar un archivo zip de un servidor FTP, que libera un nuevo zip alrededor de 13 veces al año. Necesito descargar el archivo más reciente siguiendo la convención de nombres del servidor:
Prefix + release number (one or two digits) + year (two digits) + suffix + ".zip"

Por ejemplo: ALFP1016F.zip

El prefijo siempre será el mismo (ALFP) y el sufijo F o P (significa "completo" o "parcial", solo necesito los archivos que terminan con el sufijo F). Además de eso, hay varios otros archivos en el directorio que necesito ignorar porque tienen prefijos diferentes. Entonces, necesito conseguir el archivo más reciente en la matriz después de esta orden de prioridad:

  1. Año más reciente. Por supuesto '99 no debe ser visto como el año más reciente.
  2. Número de publicación más reciente

Por ejemplo, si tengo este listado de nombres de archivo ( directorio completo del servidor ):

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

Mi producción esperada sería
ALFP716F.zip porque 16 es el año más reciente y 7 el número de publicación más reciente de ese año

.

Esto es lo que he hecho hasta ahora:

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

He hecho un intento miserable de escribir el returnMostRecent(String[]) , pero terminó con un desorden ininteligible que no vale la pena ser publicado aquí.

¿Cómo puedo ordenar esta matriz y devolver efectivamente el archivo más reciente siguiendo mi orden de prioridad?

No he probado esto, pero creo que debería funcionar.

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

Si utiliza Java8 puede hacer:

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

Donde el comparador de liberación se basa en extraer números del nombre de archivo y compararlos

Voy a sugerir este enfoque:

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

Voy a sugerir esta solución:

 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"; } 

Puede usar regex y hacer algo como esto para analizar el año y la versión:

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

Aquí está la solución compatible con Java 1.5, AlphaNumComparator

  • Significado del error Android Studio: No anotado parámetro anula parámetro @NonNull
  • Matriz de impresión en el gato de registro android
  • Cómo deshacerse de la advertencia: Utilice '$' en lugar de '.' Para clases internas en Eclipse
  • ¿Cómo puedo poner títulos en ViewPager usando fragmentos?
  • En google maps V2 ... fragment.getMap () devuelve null
  • Cancelar una conexión en curso cuando el usuario presiona de nuevo
  • Aplicación de chat en android para que el remitente y el mensaje del receptor debe estar en el lado diferente
  • Configuración de la aplicación de Android
  • El anuncio de Admob no cambia de tamaño correctamente en la orientación de la pantalla
  • Android: establece sólo un relleno de textview mediante programación
  • Comprobación para ver si existe un ID en los recursos (R.id.algo)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.