对包含string的文件名数组进行sorting

对于我的项目,我需要从FTP服务器下载一个zip文件,每年发布一个新的zip约13次。 我需要按照服务器的命名约定来下载最新的文件:
Prefix + release number (one or two digits) + year (two digits) + suffix + ".zip"

例如: ALFP1016F.zip

前缀总是相同的(ALFP),后缀是F或P(代表“全部”或“部分”;我只需要以后缀F结尾的文件)。 最重要的是,在我需要忽略的目录中还有其他几个文件,因为它们有不同的前缀。 然后,我需要按照以下优先顺序获取数组中最近的文件:

  1. 最近一年。 当然99不应该被视为最近的一年。
  2. 最近的版本号

例如,如果我有这个文件名列表( 完整的服务器目录 ):

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

我的预期产出将是
ALFP716F.zip 是因为16是最近一年,而7是当年最新的发行版本号

以下是我迄今为止所做的:

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

我已经写了returnMostRecent(String[])方法做了一个悲惨的尝试,但结束了一个难以理解的混乱不值得被张贴在这里。

我怎样才能sorting这个数组,并按照我的优先顺序有效地返回最近的文件?

Solutions Collecting From Web of "对包含string的文件名数组进行sorting"

我没有testing过,但我认为它应该工作。

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

如果你使用Java8,你可以这样做:

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

其中释放比较器是基于从文件名中提取数字并进行比较

我会build议这种方法:

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

我会build议这个解决scheme:

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

你可以使用正则expression式,并做这样的事情来parsing出年份和版本:

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

这是Java 1.5兼容的解决scheme, AlphaNumComparator