【发布时间】:2012-09-03 20:53:50
【问题描述】:
在具有新 I/O API 的 Java 7 中,是否有一种简单的方法可以按上次修改日期列出目录的内容?基本上我只需要获取最长时间未修改的文件(按最后修改的升序排序,取第一个文件名)。
【问题讨论】:
-
为什么会被标记为重复?这个问题是关于 Java NIO 的。另一个问题与 Java NIO 无关。不是重复的。
在具有新 I/O API 的 Java 7 中,是否有一种简单的方法可以按上次修改日期列出目录的内容?基本上我只需要获取最长时间未修改的文件(按最后修改的升序排序,取第一个文件名)。
【问题讨论】:
杰弗里的答案稍微“流式”变体,有些人可能会觉得更容易。发布以确保完整性。
try (DirectoryStream<Path> files = Files.newDirectoryStream(path)) {
StreamSupport.stream(files.spliterator(), false)
.sorted((o1, o2) -> {
try {
return Files.getLastModifiedTime(o1).compareTo(Files.getLastModifiedTime(o2));
} catch (IOException ex) {
...
}
})
.filter(file -> Files.isRegularFile(file))
.forEach(file -> {
});
}
【讨论】:
sorted 在filter 之前?
Call requires API level 24。 API
没有真正的“简单方法”来做到这一点,但有可能:
List<Path> files = new ArrayList<>();
try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for(Path p : stream) {
files.add(p);
}
}
Collections.sort(files, new Comparator<Path>() {
public int compare(Path o1, Path o2) {
try {
return Files.getLastModifiedTime(o1).compareTo(Files.getLastModifiedTime(o2));
} catch (IOException e) {
// handle exception
}
}
});
这将对文件中最早修改的文件进行排序。 DirectoryStreams 不会遍历子目录。
【讨论】:
Collections.sort(files, Comparator.comparingLong(File::lastModified));
在目录的 File 对象上使用 listFiles()。将数组转换为数组列表。然后使用 Collections 类上的静态排序方法和自定义 Comparator 对它们进行排序,该 Comparator 使用 Files 上的 getTotalSpace() 方法。 编辑:使用 lastModified 而不是 getTotalSpace。
【讨论】:
【讨论】:
File f = new File(""); Arrays.sort(f.listFiles(), new Comparator<File>() { public int compare(File o1, File o2) { return (int)(o1.lastModified() - o2.lastModified()); } }); return f[0];
您可以使用http://docs.oracle.com/javase/1.5.0/docs/api/java/io/File.html#listFiles(java.io.FileFilter) 并提供http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileFilter.html
然后比较 http://docs.oracle.com/javase/1.5.0/docs/api/java/io/File.html#lastModified() 就完成了
如果您确实关心性能 - 那么只需从文件列表中取一个具有最大值/最小值的值,这将为您带来 O(n) 复杂度
【讨论】:
注意:此解决方案需要 Guava。
Java IO/NIO API 提供对目录列表的低级访问,但没有完成任何处理,这留给调用者。 访问目录列表以进行进一步处理时,新的 Java7 NIO DirectoryStream 占用空间最小,例如排序。
这是我的解决方案:从 DirectoryStream 读取文件并从流中构建一个(可选)有限大小的排序队列。从队列中返回最旧/最新的元素。
private void listFilesOldestFirst(final File directory, final Integer maxNumberOfFiles) {
final Builder<File> builder =
MinMaxPriorityQueue
.orderedBy(LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
if( maxNumberOfFiles != null ) {
builder.maximumSize(maxNumberOfFiles);
}
// queue with constant space, if maxNumberOfFiles is set, otherwise behaves like an unbound queue with an O(log n) penalty for insertion
final MinMaxPriorityQueue<File> oldestFiles = builder.create();
try(DirectoryStream<Path> stream = Files.newDirectoryStream(directory.toPath())) {
for(final Path p : stream) {
oldestFiles.add(p.toFile());
}
} catch (final IOException e) {
throw new RuntimeException(e);
}
final File[] fileArray = oldestFiles.toArray(new File[]{});
Arrays.sort(fileArray, oldestFiles.comparator());
// ... use fileArray
final ArrayList<File> arrayList = Lists.newArrayList(oldestFiles);
Collections.sort(arrayList, oldestFiles.comparator());
// ... use arrayList
}
Guava MinMaxPriorityQueue 和 FileComparator 需要这些依赖项:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
您可能还会发现 Files.newDirectoryStream 的 filter 参数很有用:
final Filter<Path> sampleFilter = new Filter<Path>() {
@Override
public boolean accept(final Path entry) throws IOException {
return true; // see commons-io -> FileFilterUtils
}
};
...
Files.newDirectoryStream(directory.toPath(), sampleFilter)
【讨论】: