3

例如,我正在尝试调查一个DirecoryStream.Filter示例,newDirectoryStream以列出一个目录(及其所有子目录)下超过 60 天的所有文件。

DirectoryStream<Path> dirS = Files.newDirectoryStream(Paths.get("C:/myRootDirectory"), <DirectoryStream.filter>);

for (Path entry: dirS) {
    System.out.println(entry.toString());
}

在上面的代码中,应该是DirectoryStream.filter什么?
这将是一个很大的帮助,因为我在一个项目中试图删除早于某个时间戳的文件并且 pre-java 1.7File.listFiles()只是挂起。

可以Files.walkFileTree()提供一个选项吗?

4

2 回答 2

8

如果我做对了,你有两种情况:

  1. 创建自定义filter以选择超过 60 天的文件
  2. 遍历子目录(整个FileTree)并收集您的信息

Calendar使用类实现 60 天的条件时,自定义过滤器更容易实现:

DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
    @Override
    public boolean accept(Path entry) throws IOException {BasicFileAttributes attr = Files.readAttributes(entry,BasicFileAttributes.class);
    FileTime creationTime = attr.creationTime();
    Calendar cal = Calendar.getInstance();
    int days = cal.fieldDifference(new Date(creationTime.toMillis()),Calendar.DAY_OF_YEAR);
        return (Math.abs(days) > 60);
        }
  };

正常执行只会查找根目录中的文件。要查找子目录,您的使用猜测walkFileTree()是正确的。

然而,这需要一个FileVisitor接口的实现,幸运的是,一个简单的实现与 7 - 捆绑在一起SimpleFileVisitor

要遍历子目录,您可以选择覆盖特定于目录的方法 - 我在这里使用preVisitDirectorySimpleFileVisitor

Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path file,
                    BasicFileAttributes attrs) {

由于将在您没有任何其他限制的情况下preVisitDirectory进行定制,因此我们将利用方法在应用过滤器时一次遍历我们的目录 1。return FileVisitResult.CONTINUE;preVisitDirectory

Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path file,
                    BasicFileAttributes attrs) {

                DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
                    @Override
                    public boolean accept(Path entry) throws IOException {
                        BasicFileAttributes attr = Files.readAttributes(entry,
                                BasicFileAttributes.class);
                        FileTime creationTime = attr.creationTime();
                        Calendar cal = Calendar.getInstance();
                        int days = cal.fieldDifference(
                                new Date(creationTime.toMillis()),
                                Calendar.DAY_OF_YEAR);
                        return (Math.abs(days) > 60);
                    }
                };
                try (DirectoryStream<Path> stream = Files.newDirectoryStream(
                        file, filter)) {
                    for (Path path : stream) {
                        System.out.println(path.toString());
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                return FileVisitResult.CONTINUE;

            }
        }); 

这将为您提供所需过滤条件的整个目录和子目录结构中的文件,完成以下主要方法:

public static void main(String[] args) throws IOException {
        Path dirs = Paths.get("C:/");

        Files.walkFileTree(dirs, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path file,
                    BasicFileAttributes attrs) {

                DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
                    @Override
                    public boolean accept(Path entry) throws IOException {
                        BasicFileAttributes attr = Files.readAttributes(entry,
                                BasicFileAttributes.class);
                        FileTime creationTime = attr.creationTime();
                        Calendar cal = Calendar.getInstance();
                        int days = cal.fieldDifference(
                                new Date(creationTime.toMillis()),
                                Calendar.DAY_OF_YEAR);
                        return (Math.abs(days) > 60);
                    }
                };
                try (DirectoryStream<Path> stream = Files.newDirectoryStream(
                        file, filter)) {
                    for (Path path : stream) {
                        System.out.println(path.toString());
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                return FileVisitResult.CONTINUE;

            }
        });

    }
于 2014-02-12T18:56:39.117 回答
3

只需创建一个新实例,如果给定对象超过 60 天,该DirectoryStream.Filter实例就会返回。truePath

DirectoryStream<Path> dirStream = Files.newDirectoryStream(Paths.get("/some/path"), new Filter<Path>() {
    @Override
    public boolean accept(Path entry) throws IOException {
        FileTime fileTime = Files.getLastModifiedTime(entry);
        long millis = fileTime.to(TimeUnit.MILLISECONDS);
        Calendar today = Calendar.getInstance();
        // L is necessary for the result to correctly be calculated as a long 
        return today.getTimeInMillis() > millis + (60L * 24 * 60 * 60 * 1000);
    }
});

请注意,这只会为您提供指定目录根目录内的文件Path,即。Path参数传递给newDirectoryStream(..).

如果您还想要子目录中的所有文件,Files.walkFileTree(..)可能更容易使用。您只需要使用与上述相同的逻辑来实现一个FileVisitor存储您一路收集的对象的一个List​​或多个对象。SetPathFilter

于 2014-02-12T18:27:22.897 回答