Java 在具有多个目录的目录中搜索文件

Java 在具有多个目录的目录中搜索文件,java,Java,这是我的目标。我希望能够将父目录和文件名传递给在目录和任何子目录中搜索特定文件的方法。下面是我一直在使用的代码,但无法让它完全满足我的要求。它将找到我指定的文件,但不会返回任何内容 private static File findFile(File dir, String name) { String file = ""; File[] dirlist = dir.listFiles(); search: for(int i = 0; i &l

这是我的目标。我希望能够将父目录和文件名传递给在目录和任何子目录中搜索特定文件的方法。下面是我一直在使用的代码,但无法让它完全满足我的要求。它将找到我指定的文件,但不会返回任何内容

private static File findFile(File dir, String name) {
    String file     = "";
    File[] dirlist  = dir.listFiles();

    search:
        for(int i = 0; i < dirlist.length; i++) {
            if(dirlist[i].isDirectory()) {
                findFile(dirlist[i], name);
            } else if(dirlist[i].getName().matches(name)) {
                file = dirlist[i].toString();
                break search;
            }
        }

    return new File(file);
}
私有静态文件findFile(文件目录,字符串名称){
字符串文件=”;
File[]dirlist=dir.listFiles();
搜索:
对于(int i=0;i

我知道,当该方法找到一个目录并调用自身时,它会重置文件变量,我将在其中存储找到的文件。这就是为什么我会得到一份空白的报税表。我不确定如何实现这一目标,或者这是否可能。

问题在于,您没有从递归调用返回任何内容:

if(dirlist[i].isDirectory()) {
    findFile(dirlist[i], name); // <-- here
} else if(dirlist[i].getName().matches(name)) {
if(dirlist[i].isDirectory()){

findFile(dirlist[i],name);//事实上,有很多解决方案可以完成这项工作。 我假设您希望在目录树中找到与文件名匹配的唯一文件(或第一个文件)。 这是一个优化问题,因为有多种方法可以探索解决方案,我们希望找到一个可接受的解决方案

1-使用FileUtils.listFiles的解决方案

public static File searchFileWithFileUtils(final File file, final String fileName) {
    File target = null;
    if(file.isDirectory()) {
        Collection<File> files = FileUtils.listFiles(file, null, true);
        for (File currFile : files) {
            if (currFile.isFile() && currFile.getName().equals(fileName)) {
                target = currFile;
                break;
            }
        }
    }
    return target;
}
public static File searchFileByDeepness(final String directoryName, final String fileName) {
    File target = null;
    if(directoryName != null && fileName != null) {
        File directory = new File(directoryName);
        if(directory.isDirectory()) {
            File file = new File(directoryName, fileName);
            if(file.isFile()) {
                target = file;
            }
            else {
                List<File> subDirectories = getSubDirectories(directory);
                do {
                    List<File> subSubDirectories = new ArrayList<File>();
                    for(File subDirectory : subDirectories) {
                        File fileInSubDirectory = new File(subDirectory, fileName);
                        if(fileInSubDirectory.isFile()) {
                            return fileInSubDirectory;
                        }
                        subSubDirectories.addAll(getSubDirectories(subDirectory));
                    }
                    subDirectories = subSubDirectories;
                } while(subDirectories != null && ! subDirectories.isEmpty());
            }
        }
    }
    return target;
}

private static List<File> getSubDirectories(final File directory) {
    File[] subDirectories = directory.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(final File current, final String name) {
            return new File(current, name).isDirectory();
        }
    });
    return Arrays.asList(subDirectories);
}
该算法测试文件是否存在于任何文件夹中。如果不存在,则递归尝试当前文件夹的子文件夹。如果在当前分支中找不到该文件,则尝试另一个子文件夹

探索是深入的,对于深度为1的任何文件,算法都将探索以前所有的子文件夹(以前的分支已完全探索!)。 该算法对于第一个分支中较深位置的文件具有最佳性能

在大多数情况下,文件位置并不深,因此让我们探讨另一种适用于大多数情况的算法

3-最快的解决方案:深度勘探

public static File searchFileWithFileUtils(final File file, final String fileName) {
    File target = null;
    if(file.isDirectory()) {
        Collection<File> files = FileUtils.listFiles(file, null, true);
        for (File currFile : files) {
            if (currFile.isFile() && currFile.getName().equals(fileName)) {
                target = currFile;
                break;
            }
        }
    }
    return target;
}
public static File searchFileByDeepness(final String directoryName, final String fileName) {
    File target = null;
    if(directoryName != null && fileName != null) {
        File directory = new File(directoryName);
        if(directory.isDirectory()) {
            File file = new File(directoryName, fileName);
            if(file.isFile()) {
                target = file;
            }
            else {
                List<File> subDirectories = getSubDirectories(directory);
                do {
                    List<File> subSubDirectories = new ArrayList<File>();
                    for(File subDirectory : subDirectories) {
                        File fileInSubDirectory = new File(subDirectory, fileName);
                        if(fileInSubDirectory.isFile()) {
                            return fileInSubDirectory;
                        }
                        subSubDirectories.addAll(getSubDirectories(subDirectory));
                    }
                    subDirectories = subSubDirectories;
                } while(subDirectories != null && ! subDirectories.isEmpty());
            }
        }
    }
    return target;
}

private static List<File> getSubDirectories(final File directory) {
    File[] subDirectories = directory.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(final File current, final String name) {
            return new File(current, name).isDirectory();
        }
    });
    return Arrays.asList(subDirectories);
}
publicstaticfilesearchfilebydeepness(最终字符串directoryName,最终字符串fileName){
文件目标=null;
if(directoryName!=null&&fileName!=null){
文件目录=新文件(目录名);
if(directory.isDirectory()){
文件=新文件(目录名、文件名);
if(file.isFile()){
目标=文件;
}
否则{
List subDirectories=getSubDirectories(目录);
做{
List subSubDirectories=new ArrayList();
用于(文件子目录:子目录){
File fileInSubDirectory=新文件(子目录,文件名);
if(fileInSubDirectory.isFile()){
返回文件到目录中;
}
addAll(getsubdirectory(subDirectory));
}
子目录=子子子目录;
}while(subDirectories!=null&&!subDirectories.isEmpty());
}
}
}
回报目标;
}
私有静态列表getSubDirectories(最终文件目录){
File[]subDirectories=directory.listFiles(新文件名过滤器(){
@凌驾
公共布尔接受(最终文件当前,最终字符串名称){
返回新文件(当前,名称).isDirectory();
}
});
返回Arrays.asList(子目录);
}
对于每个深度,算法在同一级别的所有文件夹中搜索该文件。如果找不到该文件,则尝试下一个级别(深度++)。 由于并行探索(对称),此解决方案适用于大多数情况

比较:

public class FileLocationFinder {

    public static void main(final String[] args) {
        String rootFolder = args[0];
        String fileName = args[1];

        long start = System.currentTimeMillis();
        File target = searchFileWithFileUtils(new File(rootFolder), fileName);
        System.out.println(target.getAbsolutePath());
        System.out.println("Duration: " + (System.currentTimeMillis() - start) + "ms");

        start = System.currentTimeMillis();
        target = searchFileRecursive(new File(rootFolder), fileName);
        System.out.println(target.getAbsolutePath());
        System.out.println("Duration: " + (System.currentTimeMillis() - start) + "ms");

        start = System.currentTimeMillis();
        target = searchFileByDeepness(rootFolder, fileName);
        System.out.println(target.getAbsolutePath());
        System.out.println("Duration: " + (System.currentTimeMillis() - start) + "ms");
    }


    // Solution with FileUtils#listFiles
    //--------------------------------------------

    public static File searchFileWithFileUtils(final File file, final String fileName) {
        File target = null;
        if(file.isDirectory()) {
            Collection<File> files = FileUtils.listFiles(file, null, true);
            for (File currFile : files) {
                if (currFile.isFile() && currFile.getName().equals(fileName)) {
                    target = currFile;
                    break;
                }
            }
        }
        return target;
    }


    // Recursive solution
    //--------------------------------------------

    public static File searchFileRecursive(final File file, final String search) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                File target = searchFileRecursive(f, search);
                if(target != null) {
                    return target;
                }
            }
        } else {
            if (search.equals(file.getName())) {
                return file;
            }
        }
        return null;
    }


    // Fastest solution
    //--------------------------------------------

    public static File searchFileByDeepness(final String directoryName, final String fileName) {
        File target = null;
        if(directoryName != null && fileName != null) {
            File directory = new File(directoryName);
            if(directory.isDirectory()) {
                File file = new File(directoryName, fileName);
                if(file.isFile()) {
                    target = file;
                }
                else {
                    List<File> subDirectories = getSubDirectories(directory);
                    do {
                        List<File> subSubDirectories = new ArrayList<File>();
                        for(File subDirectory : subDirectories) {
                            File fileInSubDirectory = new File(subDirectory, fileName);
                            if(fileInSubDirectory.isFile()) {
                                return fileInSubDirectory;
                            }
                            subSubDirectories.addAll(getSubDirectories(subDirectory));
                        }
                        subDirectories = subSubDirectories;
                    } while(subDirectories != null && ! subDirectories.isEmpty());
                }
            }
        }
        return target;
    }

    private static List<File> getSubDirectories(final File directory) {
        File[] subDirectories = directory.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(final File current, final String name) {
                return new File(current, name).isDirectory();
            }
        });
        return Arrays.asList(subDirectories);
    }
}
公共类FileLocationFinder{
公共静态void main(最终字符串[]args){
字符串rootFolder=args[0];
字符串文件名=args[1];
长启动=System.currentTimeMillis();
文件目标=searchFileWithFileUtils(新文件(根文件夹),文件名);
System.out.println(target.getAbsolutePath());
System.out.println(“持续时间:”+(System.currentTimeMillis()-start)+“毫秒”);
start=System.currentTimeMillis();
target=searchFileRecursive(新文件(根文件夹),文件名);
System.out.println(target.getAbsolutePath());
System.out.println(“持续时间:”+(System.currentTimeMillis()-start)+“毫秒”);
start=System.currentTimeMillis();
target=searchFileByDeepness(根文件夹,文件名);
System.out.println(target.getAbsolutePath());
System.out.println(“持续时间:”+(System.currentTimeMillis()-start)+“毫秒”);
}
//使用FileUtils#listFiles的解决方案
//--------------------------------------------
公共静态文件searchFileWithFileUtils(最终文件文件,最终字符串文件名){
文件目标=null;
if(file.isDirectory()){
Collection files=FileUtils.listFiles(file,null,true);
用于(文件:文件){
if(currFile.isFile()&&currFile.getName().equals(fileName)){
目标=当前文件;
打破
}
}
}
回报目标;
}
//递归解
//--------------------------------------------
公共静态文件搜索文件递归(最终文件文件,最终字符串搜索){
if(file.isDirectory()){
File[]files=File.listFiles();
用于(文件f:文件){
文件目标=searchFileRecursive(f,搜索);
如果(目标!=null){
public static File searchFileJava8(final String rootFolder, final String fileName) {
    File target = null;
    Path root = Paths.get(rootFolder);
    try (Stream<Path> stream = Files.find(root, Integer.MAX_VALUE, (path, attr) ->
            path.getFileName().toString().equals(fileName))) {
        Optional<Path> path = stream.findFirst();
        if(path.isPresent()) {
            target = path.get().toFile();
        }
    }
    catch (IOException e) {
    }
    return target;
}