Сортировка массива имен файлов, содержащих строки с номерами
Для моего проекта мне нужно загрузить zip файл с FTP-сервера, который выпускает новый zip примерно 13 раз в год. Мне нужно загрузить последний файл в соответствии с соглашением об именах серверов:
Prefix + release number (one or two digits) + year (two digits) + suffix + ".zip"
например:
ALFP1016F.zip
Префикс всегда будет одинаковым (ALFP) и суффикс F или P (означает "полный" или "частичный", мне нужны только файлы, заканчивающиеся суффиксом F). Кроме того, в директории, которую мне нужно игнорировать, есть несколько других файлов, потому что они имеют разные префиксы. Затем мне нужно получить самый последний файл в массиве, следующий за этим порядком приоритета:
- Последний год. Конечно, '99 не следует рассматривать как самый последний год.
- Самый последний номер выпуска
Например, если у меня есть этот список имен файлов (полный каталог сервера):
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[])
, но в итоге оказался непонятным беспорядок, который не стоит публиковать здесь.
Как я могу отсортировать этот массив и эффективно вернуть последний файл после моего приоритетного порядка?
Ответы
Ответ 1
Я не тестировал это, но думаю, что он должен работать.
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
Если вы используете Java8, вы можете сделать:
String file = Arrays.stream(filenames)
.filter(s -> s.startsWith("ALFP") && s.endsWith("F.zip"))
.max(getReleaseComparator())
.orElse(null);
где компаратор релиза основан на извлечении чисел из имени файла и их сравнении
Ответ 3
Я предлагаю такой подход:
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));
}
Ответ 4
Я предлагаю это решение:
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";
}
Ответ 5
Вы можете использовать регулярное выражение и сделать что-то подобное для анализа года и версии:
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);
}
Ответ 6
Вот решение, совместимое с Java 1.5, AlphaNumComparator