我有代码删除目录中的所有文件,除了最近修改过的 n 。代码从目录中获取File
个对象的列表,使用查看File.lastModifedTime()
的比较器对它们进行排序,然后删除相应的子列表。
当我们升级到Java 7时,程序开始抛出java.lang.IllegalArgumentException: Comparison method violates its general contract!
。我怀疑这是因为在排序完成之前修改了文件(正常行为),因此比较器在检查每个文件的最后修改时间时返回不一致的值。
我的问题是,您如何解决此问题并删除正确的文件?
我读到的一个建议是在排序之前将文件存储在地图中,并将其上次修改时间,这样在比较完成后,将从地图中查找最后修改的时间。但是,如果文件在排序中更改,则地图不会更新,所以最终是否会删除错误的文件?
我想到的其他想法是使用Java NIO的文件监视来保存排序列表,并在文件发生变化时重新排序。但这看起来相当复杂。
我还想到了一种在try-catch语句中包装排序的强力方法,如果遇到比较方法违规,只需重试整个排序。
最后,我可以设置java.util.Arrays.useLegacyMergeSort
属性,然后回到静默忽略Java 6的方式。
答案 0 :(得分:0)
我的问题是,您如何解决此问题并删除正确的文件?
我建议您获取所有文件的时间戳并缓存它们。使用这些缓存时间排序。这样,他们将使用一致的时间进行排序。
File[] files = ...
final Map<File, Long> modified = new HashMap<File, Long>();
for(File file: files)
modified.put(file, file.lastModified());
Arrays.sort(files, /* Comparator using 'modified' Map */);
答案 1 :(得分:0)
根据我对更普遍的问题Best way to list files in Java, sorted by Date Modified?的回答
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());
}
}
private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
final Collection<File> result = 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 result;
}