【问题标题】:How to read files recursively in Java 7?如何在 Java 7 中递归读取文件?
【发布时间】:2012-05-09 20:25:30
【问题描述】:

我知道用于 Java 文件目录处理的 Apache Commons IO 库。不过,List all files from a directory recursively with Java 谈到了 Java 7 中的原生支持。

有没有人知道如何使用 Java 7 递归地列出/读取目录中的文件?

【问题讨论】:

    标签: java file-io java-7


    【解决方案1】:

    There's a tutorial on it。基本上,您实现了一个访问者,然后可以在进入、退出和遇到文件时调用它。支持确定文件是否是符号链接,以及遵循符号链接的选项(如果您愿意的话)。快速阅读一下 Java Paths 可能会有用,and the entire documentation starts here

    import static java.nio.file.FileVisitResult.*;
    
    public static class PrintFiles
        extends SimpleFileVisitor<Path> {
    
        // Print information about
        // each type of file.
        @Override
        public FileVisitResult visitFile(Path file,
                                       BasicFileAttributes attr) {
            if (attr.isSymbolicLink()) {
                System.out.format("Symbolic link: %s ", file);
            } else if (attr.isRegularFile()) {
                System.out.format("Regular file: %s ", file);
            } else {
                System.out.format("Other: %s ", file);
            }
            System.out.println("(" + attr.size() + "bytes)");
            return CONTINUE;
        }
    
        // Print each directory visited.
        @Override
        public FileVisitResult postVisitDirectory(Path dir,
                                              IOException exc) {
            System.out.format("Directory: %s%n", dir);
            return CONTINUE;
        }
    
        // If there is some error accessing
        // the file, let the user know.
        // If you don't override this method
        // and an error occurs, an IOException 
        // is thrown.
        @Override
        public FileVisitResult visitFileFailed(Path file,
                                           IOException exc) {
            System.err.println(exc);
            return CONTINUE;
        }
    }
    

    说明文件遍历的第二个示例(来自 find 的 Java 实现)可以轻松修改为“匹配”所有文件。

    /*
     * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *   - Redistributions of source code must retain the above copyright
     *     notice, this list of conditions and the following disclaimer.
     *
     *   - Redistributions in binary form must reproduce the above copyright
     *     notice, this list of conditions and the following disclaimer in the
     *     documentation and/or other materials provided with the distribution.
     *
     *   - Neither the name of Oracle or the names of its
     *     contributors may be used to endorse or promote products derived
     *     from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    import java.io.*;
    import java.nio.file.*;
    import java.nio.file.attribute.*;
    import static java.nio.file.FileVisitResult.*;
    import static java.nio.file.FileVisitOption.*;
    import java.util.*;
    
    /**
     * Sample code that finds files that
     * match the specified glob pattern.
     * For more information on what
     * constitutes a glob pattern, see
     * http://docs.oracle.com/javase/javatutorials/tutorial/essential/io/fileOps.html#glob
     *
     * The file or directories that match
     * the pattern are printed to
     * standard out.  The number of
     * matches is also printed.
     *
     * When executing this application,
     * you must put the glob pattern
     * in quotes, so the shell will not
     * expand any wild cards:
     *     java Find . -name "*.java"
     */
    
    public class Find {
    
        /**
         * A {@code FileVisitor} that finds
         * all files that match the
         * specified pattern.
         */
        public static class Finder
            extends SimpleFileVisitor<Path> {
    
            private final PathMatcher matcher;
            private int numMatches = 0;
    
            Finder(String pattern) {
                matcher =
                    FileSystems.getDefault()
                        .getPathMatcher("glob:" + pattern);
            }
    
            // Compares the glob pattern against
            // the file or directory name.
            void find(Path file) {
                Path name = file.getFileName();
                if (name != null && matcher.matches(name)) {
                    numMatches++;
                    System.out.println(file);
                }
            }
    
            // Prints the total number of
            // matches to standard out.
            void done() {
                System.out.println("Matched: "
                    + numMatches);
            }
    
            // Invoke the pattern matching
            // method on each file.
            @Override
            public FileVisitResult
                visitFile(Path file,
                    BasicFileAttributes attrs) {
                find(file);
                return CONTINUE;
            }
    
            // Invoke the pattern matching
            // method on each directory.
            @Override
            public FileVisitResult
                preVisitDirectory(Path dir,
                    BasicFileAttributes attrs) {
                find(dir);
                return CONTINUE;
            }
    
            @Override
            public FileVisitResult
                visitFileFailed(Path file,
                    IOException exc) {
                System.err.println(exc);
                return CONTINUE;
            }
        }
    
        static void usage() {
            System.err.println("java Find <path>" +
                " -name \"<glob_pattern>\"");
            System.exit(-1);
        }
    
        public static void main(String[] args)
            throws IOException {
    
            if (args.length < 3 
                || !args[1].equals("-name"))
                usage();
    
            Path startingDir = Paths.get(args[0]);
            String pattern = args[2];
    
            Finder finder = new Finder(pattern);
            Files.walkFileTree(startingDir, finder);
            finder.done();
        }
    }
    

    在我的系统(Linux / Fedora)上,它运行良好;然而,我只是在测试它的功能,并玩弄它。我没有对它的性能或任何其他有意义的测量进行压力测试(除了“它有效”)。

    【讨论】:

      【解决方案2】:

      使用Files.walkFileTree

      (没有使用它的经验,但我只是在文档中找到了它,看起来使用起来很简单。)

      【讨论】:

      • @EdwinBuck ...是的。我不确定您要通过评论解决什么问题。
      • Files.walkFileTree 返回一个Path,而Paths 本身什么也不做。 FileVisitor 可以“遍历”Path 并“发现”Path 中的文件,可能会跳过不感兴趣的文件或子目录。您的解决方案是所需的一部分(因为它提供了Path 部分)但没有访客,您将永远看不到File
      • @EdwinBuck Files.walkFileTree 实际上返回“起始文件”,这将是您传递给它的路径。此外,如果没有FileVisitor,它就无法使用,因此如果没有实现实际工作的FileVisitor,就不可能“使用Files.walkFileTree”。我链接到的文档中都非常清楚地说明了这一点。我认为这使我的回答足够了。
      • 仅链接的答案是重定向,devinb 比我更好地描述了他们的问题。meta.stackexchange.com/a/8259/158374 你的答案足以找到答案,但实际上没有什么比 devinb 的(修改后的)引用更好的了我会带您到 API 信息亭,他们将能够为您提供答案等等!”
      • @EdwinBuck 当他问“这里有人钓鱼吗?”时,我宁愿指点一个人去钓鱼学校,也不愿给他一条鱼和一条海豚。
      猜你喜欢
      • 2015-05-03
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-29
      • 2014-11-05
      • 2011-01-13
      • 2017-03-09
      相关资源
      最近更新 更多