Java DirectoryStream.Filter 示例,用于列出基于特定日期/时间的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21733390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:24:41  来源:igfitidea点击:

DirectoryStream.Filter example for listing files that based on certain date/time

javafile-ionio2

提问by Ashley

I am trying to investigate a DirecoryStream.Filterexample for newDirectoryStreamwhere I can achieve to list all files under a directory(and all its sub directories) that are older than 60 days, as an example.

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

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

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

In the code above, what should be the DirectoryStream.filter?
It will be a great help as I am in a project where I am trying to delete files older than a certain timestamp and pre-java 1.7 File.listFiles()just hangs.

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

Could Files.walkFileTree()provide an option?

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

采纳答案by PopoFibo

If I get this right, you have 2 situations:

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

  1. Create a custom filterto select files older than 60 days
  2. Traverse through subdirectories (the entire FileTree) and gather your information
  1. 创建自定义filter以选择超过 60 天的文件
  2. 遍历子目录(整个FileTree)并收集您的信息

The custom filter is easier to implement with conditions of 60 days implemented using Calendarclass:

使用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);
        }
  };

The normal execution would only look for the files in the root directory. To look for subdirectory, your guess of using walkFileTree()is right.

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

However, this requires an implementation of the FileVisitorinterface, a simple implementation of which luckily is bundled with 7 - SimpleFileVisitor.

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

To traverse through the subdirectories, you can choose to override a directory specific method - I have used preVisitDirectoryof SimpleFileVisitorhere:

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

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

Since preVisitDirectorywill be custom made to return FileVisitResult.CONTINUE;in case you don't have any additional restrictions, we would leverage preVisitDirectorymethod to iterate through our directory 1 at a time while applying the filter.

由于preVisitDirectory将是定制的return FileVisitResult.CONTINUE;,以防您没有任何其他限制,我们将利用preVisitDirectory方法在应用过滤器时一次迭代我们的目录 1。

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;

            }
        }); 

This would give you the files from the entire directory and subdirectory structures for the required filter criteria, complete main method below:

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

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;

            }
        });

    }

回答by Sotirios Delimanolis

Simply create a new DirectoryStream.Filterinstance that returns trueif the given Pathobject is older than 60 days.

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

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);
    }
});

Note that this will only give you the files inside the root of the specified directory Path, ie. the Pathargument passed to newDirectoryStream(..).

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

If you want all files in sub directories as well, Files.walkFileTree(..)is probably easier to use. You'll just have to implement a FileVisitorthat stores a Listor Setof Pathobjects that you collect along the way using the same logic as the Filterabove.

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