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
- Combinar dos animaciones en Android
- Java.lang.NoClassDefFoundError: com / android / utils / ILogger en Visual Studio 2015
- Cambiar de AndEngine a libgdx - qué saber?
- Facebook, setReadPermissions y setPublishPermissions
- ¿Soporta Android el cultivo de video?
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:
- Año más reciente. Por supuesto '99 no debe ser visto como el año más reciente.
- 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?
- Excepción de tiempo de ejecución al utilizar la configuración de Android (estoy siguiendo el curso de desarrollo de Android de udacity)
- Android getRelativeTimeSpanString () error?
- Error de eclipse con complementos después de la actualización
- Exportar clave pública RSA a PEM String utilizando java
- ¿cómo volver a la actividad principal en android?
- Java.lang.SecurityException: Permiso Denial: Intención inicial {act = android.intent.action.MAIN cat =
- Eclipse no se inicia (Ubuntu): termina JVM. Código de salida = 2
- IndexOutOfBoundsException después de repoblar ArrayList (sólo Marshmallow)
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