简体   繁体   English

在Java中以递归方式处理许多子目录中的相同文件

[英]Recursively process same files inside many sub directories in Java

Hi I would like to process files inside many sub directories using Java. 嗨,我想使用Java处理许多子目录中的文件。 Psuedo code would be Psuedo代码将是

while(mainDir.hasMoreDirectory())
{
   getFilesFromCurrentDirectory()
   passThoseFilesAsArgumentToProcess()
}

I am currently using the following code 我目前正在使用以下代码

public void list(File file) {
    System.out.println(file.getName());
    File[] children = file.listFiles();
    for (File child : children) {
        list(child);
    }
}

Above code just lists files. 上面的代码只列出文件。 Other thing I can do is I have to store list of files and directories in a list and then process in another loop. 我能做的其他事情是我必须在列表中存储文件和目录列表,然后在另一个循环中处理。 But I am not able to come up with what I want as show in pseudo code. 但我无法想出伪代码中显示的内容。 I am new to Files Directories please help. 我是文件目录的新手,请帮忙。 Thanks in advance. 提前致谢。

If you are using Java 7, you can harness the enhanced functionality of NIO in the form of the Files.walkFileTree method. 如果您使用的是Java 7,则可以使用Files.walkFileTree方法的形式利用NIO的增强功能。 Traversing the file system has never been easier in Java. 在Java中遍历文件系统从未如此简单。

There is a short tutorial on it's usage here . 有它的使用一个简短的教程这里

It implements the visitor pattern so you don't need to worry about the traversal algorithm itself, only specify what you want to do with each entry. 它实现了访问者模式,因此您无需担心遍历算法本身,只需指定您要对每个条目执行的操作。

When traveling a directory tree in Java 7 use the Paths and Files functionality. 在Java 7中运行目录树时,请使用“ PathsFiles功能。 They not only ease reading of directories and files, they're way faster then the "old" File way. 它们不仅简化了目录和文件的读取,而且比“旧” File方式更快。

Assume you have two directories: mainDir and otherDir and you want to walk thru all directories of mainDir down to its leaves. 假设你有两个目录: mainDirotherDir ,你想要通过mainDir所有目录到它的叶子。 With each entry in maiondir (file, sub-directory, symbolic link, ...) you want to compare this entry and its attributes (size, modification time, ...) against the entry at the same position in the otherDir . 对于maiondir每个条目(文件,子目录,符号链接,...),您希望将此条目及其属性(大小,修改时间......)与otherDir相同位置的条目进行otherDir Then this would be your code: 那么这将是你的代码:

public final void test() throws IOException, InterruptedException {
    final Path mainDir = Paths.get("absolute path to your main directory to read from");
    final Path otherDir = Paths.get("absolute path to your other directory to compare");

    // Walk thru mainDir directory
    Files.walkFileTree(mainDir, new FileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path path,
                BasicFileAttributes atts) throws IOException {
            return visitFile(path, atts);
        }

        @Override
        public FileVisitResult visitFile(Path path, BasicFileAttributes mainAtts)
                throws IOException {
            // I've seen two implementations on windows and MacOSX. One has passed the relative path, one the absolute path.
            // This works in both cases
            Path relativePath = mainDir.relativize(mainDir.resolve(path));

            BasicFileAttributes otherAtts = Files.readAttributes(otherDir.resolve(relativePath), BasicFileAttributes.class);

            // Do your comparison logic here:
            compareEntries(mainDir, otherDir, relativePath, mainAtts, otherAtts);

            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path path,
                IOException exc) throws IOException {
            // TODO Auto-generated method stub
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path path, IOException exc)
                throws IOException {
            exc.printStackTrace();

            // If the root directory has failed it makes no sense to continue
            return (path.equals(mainDir))? FileVisitResult.TERMINATE:FileVisitResult.CONTINUE;
        }
    });
}

What it not does: 没有做什么:

  • Find entries that do exist in otherDir but not in maindir 查找在otherDir存在但在maindir中不存在的条目
  • Path and BasicFileAttributes are not Serializable , so there's no easy way to do this walk on two different machines. PathBasicFileAttributes不是Serializable ,因此没有简单的方法可以在两台不同的机器上执行此操作。

Will following do? 会跟着吗?

public void list(File file) {
    File[] children = file.listFiles();

    if (children != null) {
        process(children);

        for (File child : children) {
            if (child.isDirectory()) {
                list(child);
            }
        }
    } else {
        process(new File[]{file});
    }
}

private void process(File[] children) {
    for (File child : children) {
        if (child.isFile()) {
            // process normal file
        }
    }
}

A method like this would return you a List of all the files recursively within a directory. 像这样的方法会在目录中递归返回所有文件的List You can either operate on the returned List or replace the rtn.add calls with your processing. 您可以对返回的List进行操作,也可以使用您的处理替换rtn.add调用。

Beware that this method doesn't have anything to stop it getting stuck in circular symlinks. 请注意,此方法没有任何东西可以阻止它卡在循环符号链接中。

public static List<File> getFilesRecursive(File s)
{
    ArrayList<File> rtn = new ArrayList<File>();
    File[] contents = s.listFiles();
    for(int i = 0; i<contents.length; i++)
    {
        if(contents[i].isDirectory()){
            rtn.addAll(getFilesRecursive(contents[i]));
        }else{
            rtn.add(contents[i]);
        }
    }
    return rtn;
}

Maybe this piece of code helps you: 也许这段代码可以帮助你:

public void traverse(String path) {
    File root = new File(path);
    File[] list = root.listFiles();
    if (list == null) return;

    for (File file : list) {
        if (file.isDirectory()) {
            traverse(file.getAbsolutePath());
            System.out.println("Directory: " + file.getAbsoluteFile());
        } else {
            System.out.println("File: " + file.getAbsoluteFile());
        }
    }
}
private static List<File> allFiles = new ArrayList<File>();

private static void processFiles(String rootDirectory) {
    File rootDir = new File(rootDirectory);
    if (rootDir.exists()) {
        traverseDirectories(rootDir);
    }
}

private static void traverseDirectories(File file) {
    // add all files and directories to list.
    allFiles.add(file);
    if (file.isDirectory()) {
        File[] fileList = file.listFiles();
        for (File fileHandle : fileList) {
            traverseDirectories(fileHandle);
        }
    } else {
        // call to process file
        System.out.println("Call to process file " + file.getAbsolutePath());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM