我的代码可以删除目录中除最后n个最近修改的文件之外的所有文件。该代码从目录中获取File
对象的列表,使用查看File.lastModifedTime()
的比较器对它们进行排序,然后删除适当的子列表。
当我们升级到Java7时,程序开始抛出java.lang.IllegalArgumentException: Comparison method violates its general contract!
。我怀疑这是因为文件在排序完成之前被修改(正常行为),所以比较器在检查每个文件的最后修改时间时返回不一致的值。
我的问题是,如何解决这个问题并删除正确的文件?
我读到的一个建议是在排序之前将文件及其上次修改时间存储在映射中,以便在进行比较时,从映射中查找上次修改时间。但是,如果文件更改了中间排序,映射不会更新,因此您最终不会删除错误的文件吗?
我想到的另一个想法是使用Java NIO的文件监视来保存排序列表,并在文件发生更改时重新排序。但这似乎相当复杂。
我还想到了一种强力方法,将sort包装在try-catch语句中,如果遇到比较方法冲突,就重试整个sort。
最后,我可以只设置java.util.Arrays.useLegacyMergeSort
属性,然后回到Java6的静默忽略方式。
发布于 2019-02-19 11:42:23
摘自我对更一般的问题Best way to list files in Java, sorted by Date Modified?的回答
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;
}
https://stackoverflow.com/questions/20431031
复制相似问题