18

在具有新 I/O API 的 Java 7 中,是否有一种按上次修改日期列出目录内容的简单方法?基本上我只需要获取最长时间未修改的文件(按最后修改的升序排序,取第一个文件名)。

4

6 回答 6

23

没有真正的“简单方法”可以做到这一点,但有可能:

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 不遍历子目录。

于 2012-09-03T21:03:09.227 回答
8

杰弗里的答案稍微“流”变,有些人可能会觉得更容易。发布以确保完整性。

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 -> {
        });
}
于 2015-06-02T14:42:38.443 回答
2

在目录的 File 对象上使用 listFiles()。将数组转换为数组列表。然后使用 Collections 类上的静态排序方法和自定义 Comparator 对它们进行排序,该 Comparator 使用 Files 上的 getTotalSpace() 方法。编辑:使用 lastModified 而不是 getTotalSpace。

于 2012-09-03T21:00:33.957 回答
0
lastModified()

返回此抽象路径名表示的文件最后一次修改的时间。

Java 7 - IO API

于 2012-09-03T20:57:40.383 回答
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) 复杂性

于 2012-09-03T20:59:48.230 回答
0

注意:此解决方案需要 Guava。

Java IO/NIO API 提供对目录列表的低级访问,但没有完成任何处理,这留给调用者。在访问目录列表以进行进一步处理(例如排序)时,新的 J ava7 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 MinMaxPriorityQueueFileComparator需要这些依赖项:

    <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)
于 2014-11-17T07:48:26.160 回答