所以,我有此文件夹列表,该文件夹代表程序的版本,我想获取最新的文件(文件夹旁边有一些垃圾文件!):
0.0.0.256
0.0.1.1
0.0.1.2
0.0.1.5
0.0.1.11
0.0.1.68
0.0.2.1
等等。
如果我只想在此处获取最新版本的文件夹,我该如何完成?
目前,我知道该版本目前不会上升高于0.0.1.x,(以上只是一个示例),因此我可以使用
for(String name:names)
{
if (name.indexOf("0.0.1")==0)
{
ret = name;
}
}
System.out.println("Current Installed Version Folder: "+ret);
但是那不会永远持续下去。我该如何编写一些代码,这始终会给我最高的代表性版本编号?我可以想到一种方法,现在可以做到这一点(检查0个字符,然后是第二,第4个炭),但我认为有一种更聪明的方法。有什么快速的想法?
这个想法是使用比较器比较每个字符串(我删除了使用集合的零件):
public static void main(String [] args){
String [] names = { "0.0.1.1",
"1.0.1.1",
"0.0.1.2",
"0.0.1.5",
"0.0.1.11",
"0.0.0.100",
"0.0.0.256",
"0.0.2.1",
"0.0.1.68"};
String maxVersion = names[0];
for(int i = 1; i < names.length; i++){
if(compare(maxVersion, names[i]) == 1)
maxVersion = names[i];
}
System.out.print(maxVersion);
}
static int compare(String a, String b){
String[] sA = a.split("\.");
String[] sB = b.split("\.");
for(int i = 0; i < sA.length; i++){
int cmp = Integer.compare(Integer.parseInt(sB[i]), Integer.parseInt(sA[i]));
if(cmp != 0)
return cmp;
}
return 0;
}
输出:
"1.0.1.1"
请注意,这假定每个版本号的长度相同,但是您可以通过检查分裂时的阵列的长度来更改此操作。
我遇到了另一个问题:我在版本文件夹旁边有一些文件, 因此,我无法从file.list()
获得名称列表
您可以使用listFiles
方法提供FileNameFilter
:
File file = new File("/pathToVersionFolders");
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
});
现在您只有目录。如果您只想获得名称,则可以使用list
。
如果要使用Java 8流API,则必须编写自定义比较器。
List<String> sortedVersions = versions.stream().sorted((o1, o2) -> {
String[] o1Split = o1.split("\.");
String[] o2Split = o2.split("\.");
int i = 0;
while (i++ < Math.min(o2Split.length, o1Split.length)) {
int o1IntValue = Integer.parseInt(o1Split[i - 1]);
int o2IntValue = Integer.parseInt(o2Split[i - 1]);
if (o1IntValue != o2IntValue) {
return o1IntValue - o2IntValue;
}
}
return 0;
}).collect(Collectors.toList());
String highestVersion = sortedVersions.get(sortedVersions.size() - 1);
System.out.println(highestVersion);
当前接受的答案假设您始终具有完全相同的编号方案,这在您的情况下可能是正确的。然后,您提到的"垃圾文件"将使用isDirectory()
过滤器过滤出来,但是如果您有一些垃圾目录,该怎么办?
一个更通用的解决方案不会关心确切的版本控制方案,而是将输入文件名称分为一组数字/非数字段,然后通过匹配段数字订购文件(如果两者都是数字,则字母为字母,则否则)。我在这里写了有关这种方法的博客。这个想法在这里受到此答案的启发。比较器看起来像这样:
public final class FilenameComparator implements Comparator<String> {
private static final Pattern NUMBERS =
Pattern.compile("(?<=\D)(?=\d)|(?<=\d)(?=\D)");
@Override public final int compare(String o1, String o2) {
// Optional "NULLS LAST" semantics:
if (o1 == null || o2 == null)
return o1 == null ? o2 == null ? 0 : -1 : 1;
// Splitting both input strings by the above patterns
String[] split1 = NUMBERS.split(o1);
String[] split2 = NUMBERS.split(o2);
for (int i = 0; i < Math.min(split1.length, split2.length); i++) {
char c1 = split1[i].charAt(0);
char c2 = split2[i].charAt(0);
int cmp = 0;
// If both segments start with a digit, sort them numerically using
// BigInteger to stay safe
if (c1 >= '0' && c1 <= '9' && c2 >= 0 && c2 <= '9')
cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i]));
// If we haven't sorted numerically before, or if numeric sorting yielded
// equality (e.g 007 and 7) then sort lexicographically
if (cmp == 0)
cmp = split1[i].compareTo(split2[i]);
// Abort once some prefix has unequal ordering
if (cmp != 0)
return cmp;
}
// If we reach this, then both strings have equally ordered prefixes, but
// maybe one string is longer than the other (i.e. has more segments)
return split1.length - split2.length;
}
}
由于版本编号将始终具有此结构[0-9]+(.[0-9]+)*
,因此您可以扫描目录中适合此模式的文件夹名称。
获得版本目录的列表后,您可以将它们分为单独的数字(在'。'字符上分开),然后将它们分类在从左到右的列上。
这些解决方案很多。例如
-
.
将字符串拆分 - 在结果数组上迭代并通过将当前数字添加到结果 * 10, 来创建整数
- 比较结果数
这是一种伪代码。
long version = 0;
String[] parts = versionSpec.split("\.");
for (String part : parts) {
int n = part.length;
version = version * n + Integer.parseInt(part);
}
//此时,您具有版本的数字表示。
现在您可以根据需要比较版本。例如,您可以实现自己的Comparator
。
编辑:解决方案已修复。现在,n
是动态计算的。
这对我有用,但根据程序的更新方式可能对他人不起作用。
我使用文件的 lastModified
属性来确定要修改的最新版本目录。就我而言,最近修改的文件夹也是该程序的最新/最高版本。它为我节省了很多字符串解析。
使用directory.listFiles()
获取该目录中所有文件夹的数组,然后将其传递给该方法以在最后一个修改的文件夹的数组中获取索引。然后,filelist [index]将是程序的最新版本文件夹。
/**
* Determine the index in an array of files[] of the most recently modified file
* by comparing the lastModified property from all files in the array.
*
* @param fileList Array of files from a desired directory
* @return Integer index of most recently modified file/directory.
* Returns -1 if the File[] array is null.
*/
public static int getLatestModified(File[] fileList){
if(fileList!= null){
long latestVersion = 0;
int index = 0;
for(int i = 0; i < fileList.length; i++){
File currentDir = fileList[i];
if(currentDir.lastModified() > latestVersion){
latestVersion = currentDir.lastModified();
index = i;
}
}
return index;
}else{
System.out.println("Error: fileList is null.");
return -1;
}
}
编辑:如果版本的同一目录中的文件和文件夹,则可以添加一个带有isDirectory
的IF语句,以仅从文件夹中获取LastModified属性。
使用Java 8,您可以使用流和自然顺序比较器。例如:
List<String> versions = Arrays.asList(
"0.0.1.1",
"1.0.1.1",
"0.2.1.11",
"0.0.1.2",
"0.0.1.5",
"0.1.11",
"0.1.1.11",
"0.0.0.100",
"0.0.0.256",
"2.0.0.256",
"1.0.0.256",
"0.0.2.1",
"0.0.1.68");
String highest = versions.stream()
.sorted(Comparator.naturalOrder())
.collect(Collectors.toList())
.get(versions.size() - 1);
System.out.println(highest);