题
我想获取目录中的文件列表,但我想对其进行排序,使得最旧的文件是第一个。我的解决方案是调用File.listFiles并根据File.lastModified求助于列表,但我想知道是否有更好的方法。
编辑:我建议的当前解决方案是使用匿名比较器:
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator<File>(){
public int compare(File f1, File f2)
{
return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
} });
解决方案
我认为您的解决方案是唯一明智的方法。获取文件列表的唯一方法是使用 File.listFiles()和文档声明这不保证返回的文件的顺序。因此,您需要编写一个使用的 Comparator File.lastModified()并将此文件与文件数组一起传递给 Arrays.sort()。
其他提示
如果你有很多文件,这可能会更快。这使用了decorate-sort-undecorate模式,这样每个文件的最后修改日期只能一次而不是每次排序算法比较两个文件时。这可能会减少从O(n log n)到O(n)的I / O调用次数。
这是更多的代码,所以只有在你主要关心速度时它才会被使用,而且在实践中它的速度要快得多(我没有检查过)。
class Pair implements Comparable {
public long t;
public File f;
public Pair(File file) {
f = file;
t = file.lastModified();
}
public int compareTo(Object o) {
long u = ((Pair) o).t;
return t < u ? -1 : t == u ? 0 : 1;
}
};
// Obtain the array of (file, timestamp) pairs.
File[] files = directory.listFiles();
Pair[] pairs = new Pair[files.length];
for (int i = 0; i < files.length; i++)
pairs[i] = new Pair(files[i]);
// Sort them by timestamp.
Arrays.sort(pairs);
// Take the sorted pairs and extract only the file part, discarding the timestamp.
for (int i = 0; i < files.length; i++)
files[i] = pairs[i].f;
类似的方法是什么,但没有拳击到Long对象:
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator<File>() {
public int compare(File f1, File f2) {
return Long.compare(f1.lastModified(), f2.lastModified());
}
});
自Java 8以来的优雅解决方案:
File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified));
或者,如果您想按降序排列,只需将其反转:
File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
您还可以查看 apache commons IO ,它内置了上次修改后的比较器和许多其他用于处理文件的好工具。
在Java 8中:
Arrays.sort(files,(a,b) - &gt; Long.compare(a.lastModified(),b.lastModified()));
进口:
org.apache.commons.io.comparator.LastModifiedFileComparator
代码:
public static void main(String[] args) throws IOException {
File directory = new File(".");
// get just files, not directories
File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE);
System.out.println("Default order");
displayFiles(files);
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
System.out.println("\nLast Modified Ascending Order (LASTMODIFIED_COMPARATOR)");
displayFiles(files);
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
System.out.println("\nLast Modified Descending Order (LASTMODIFIED_REVERSE)");
displayFiles(files);
}
如果您正在排序的文件可以在执行排序的同时进行修改或更新:
Java 8 +
private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
return fileStream
.map(Path::toFile)
.collect(Collectors.toMap(Function.identity(), File::lastModified))
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
// .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // replace the previous line with this line if you would prefer files listed newest first
.map(Map.Entry::getKey)
.map(File::toPath) // remove this line if you would rather work with a List<File> instead of List<Path>
.collect(Collectors.toList());
}
}
Java 7
private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
final List<File> files = Arrays.asList(new File(directoryPath).listFiles());
final Map<File, Long> constantLastModifiedTimes = new HashMap<File,Long>();
for (final File f : files) {
constantLastModifiedTimes.put(f, f.lastModified());
}
Collections.sort(files, new Comparator<File>() {
@Override
public int compare(final File f1, final File f2) {
return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2));
}
});
return files;
}
,点击 这两种解决方案都创建了一个临时的地图数据结构,以便为目录中的每个文件保存一个不变的上次修改时间。我们需要这样做的原因是,如果在执行排序时更新或修改了文件,那么比较器将违反比较器接口的一般合同的传递性要求,因为在比较期间最后修改的时间可能会发生变化。
另一方面,如果您知道在排序过程中不会更新或修改文件,您可以放弃提交此问题的其他任何答案。
public String[] getDirectoryList(String path) {
String[] dirListing = null;
File dir = new File(path);
dirListing = dir.list();
Arrays.sort(dirListing, 0, dirListing.length);
return dirListing;
}
您可以尝试guava 订购一个>:
Function<File, Long> getLastModified = new Function<File, Long>() {
public Long apply(File file) {
return file.lastModified();
}
};
List<File> orderedFiles = Ordering.natural().onResultOf(getLastModified).
sortedCopy(files);
您可以使用Apache LastModifiedFileComparator 库
import org.apache.commons.io.comparator.LastModifiedFileComparator;
File[] files = directory.listFiles();
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
for (File file : files) {
Date lastMod = new Date(file.lastModified());
System.out.println("File: " + file.getName() + ", Date: " + lastMod + "");
}
private static List<File> sortByLastModified(String dirPath) {
List<File> files = listFilesRec(dirPath);
Collections.sort(files, new Comparator<File>() {
public int compare(File o1, File o2) {
return Long.compare(o1.lastModified(), o2.lastModified());
}
});
return files;
}
Collections.sort(listFiles, new Comparator<File>() {
public int compare(File f1, File f2) {
return Long.compare(f1.lastModified(), f2.lastModified());
}
});
其中 listFiles
是ArrayList
当我在 android
中搜索相同的问题时,我来到这篇文章。
我不是说这是在上次修改日期之前获取排序文件的最佳方式,但这是我发现的最简单方法。
下面的代码可能对某人有帮助 -
File downloadDir = new File("mypath");
File[] list = downloadDir.listFiles();
for (int i = list.length-1; i >=0 ; i--) {
//use list.getName to get the name of the file
}
由于
有一种非常简单方便的方法来处理问题而无需任何额外的比较器。只需使用文件名将修改后的日期编码到String中,对其进行排序,然后再将其剥离。
使用固定长度为20的字符串,将修改日期(长)放入其中,并填充前导零。然后只需将文件名附加到此字符串:
String modified_20_digits = ("00000000000000000000".concat(Long.toString(temp.lastModified()))).substring(Long.toString(temp.lastModified()).length());
result_filenames.add(modified_20_digits+temp.getAbsoluteFile().toString());
这里发生了什么:
Filename1:C:\ data \ file1.html Last Modified:1532914451455 Last Modified 20 Digits:00000001532914451455
Filename1:C:\ data \ file2.html Last Modified:1532918086822 Last Modified 20 Digits:00000001532918086822
将filnames转换为:
文件名1:00000001532914451455C:\ data \ file1.html
文件名2:00000001532918086822C:\ data \ file2.html
然后您可以对此列表进行排序。
您需要做的就是稍后再次删除20个字符(在Java 8中,您可以使用.replaceAll函数仅使用一行删除整个数组)
还有一种完全不同的方式可能更容易,因为我们不处理大数字。
在检索完所有文件名和lastModified日期后,您只需在列表的正确位置检索到每个文件后,就可以插入每个文件名。
你可以这样做:
list.add(1, object1)
list.add(2, object3)
list.add(2, object2)
将object2添加到位置2后,它会将object3移动到位置3。