【问题标题】:DirectoryStream.Filter example for listing files that based on certain date/timeDirectoryStream.Filter 示例,用于列出基于特定日期/时间的文件
【发布时间】:2014-02-12 16:13:38
【问题描述】:

我正在尝试调查 newDirectoryStreamDirecoryStream.Filter 示例,我可以在其中列出目录(及其所有子目录)下超过 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.7 File.listFiles() 只是挂起。

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

【问题讨论】:

    标签: java file-io nio2


    【解决方案1】:

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

    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 将自定义为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;
    
                }
            }); 
    

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

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

    【讨论】:

    • 感谢您提供这些详细信息。
    【解决方案2】:

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

    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 来存储 ListSetPath 对象,使用与上述 Filter 相同的逻辑收集这些对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 1970-01-01
      • 1970-01-01
      • 2017-01-12
      • 1970-01-01
      • 2014-02-05
      相关资源
      最近更新 更多