对包含带数字的字符串的文件名数组进行排序

时间:2016-03-16 15:51:09

标签: java android arrays algorithm 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. 最新版本号
  3. 例如,如果我有这个文件名列表(full server directory):

    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[])方法方面做了一次悲惨的尝试,但结果却发现了一个难以理解的混乱,不值得在这里发布。

    如何对此数组进行排序并按照优先顺序有效地返回最新文件?

6 个答案:

答案 0 :(得分:5)

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

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

其中,发布比较器基于从文件名中提取数字并进行比较

答案 1 :(得分:3)

我没有对此进行测试,但我认为它应该可行。

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

答案 2 :(得分:2)

我会建议这种方法:

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

}

答案 3 :(得分:2)

我会建议这个解决方案:

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

答案 4 :(得分:1)

您可以使用正则表达式并执行类似的操作来解析年份和版本:

<script type="text/javascript">
var PageApiCtor = {
    TempProfilePicUrl: '@Url.Action("TempPic", "Member")',
    CropUrl: '@Url.Action("CropAndSave", "Member")',
    DeletePicUrl: '@Url.Action("DeletePic", "Member")',
    NoPicUrl: '@Url.Content("~/Content/images/no-pic.gif")',
    LastProfileRef: undefined
};

答案 5 :(得分:1)

这是Java 1.5兼容的解决方案,AlphaNumComparator