在大目录中搜索多个文件夹 - JAVA

Searching Large Directories for Multiple Folders - JAVA

我希望能够搜索一个大目录,包括名为“online”的 every 文件夹的所有子文件夹,并添加这些文件夹一旦找到一个列表。

换句话说:这个文件是一个文件夹吗?如果没有忽略,如果是,这个文件夹叫 "online" 吗?如果是,添加到列表,如果没有打开并循环浏览文件夹内容,然后重新开始。

我有一个脚本:

String fileType = "online";

private void buildList(File aFile) {
 if (aFile.isDirectory()) {

    if (fileName.contains(fileType)) {
        addToList(aFile);
    } else {
        for (File bFile : aFile.listFiles()) {
            buildList(bFile);
        }
    }
 }
}

这在小目录上效果很好,但在大目录上效果不佳,因为它打开的数组数量很大。它挂起并用完所有内存。

我乐于接受所有建议。 JAVA 仅与 JDK1.6 兼容。非常感谢您!!!!

编辑:

static long counter = 0L;
ArrayList<File> opFolders;


public final class DirectoryCollectorVisitor extends SimpleFileVisitor<Path> {

   private final List<Path> list;



   public DirectoryCollectorVisitor(final List<Path> list) {


      this.list = list;
    }

    @Override
    public FileVisitResult preVisitDirectory(final Path path, final BasicFileAttributes attrs) {
        counterPrintField.setText("" + counter++);
        if (path.getFileName().toString().contains("online")) {
            list.add(path);
            File aFile = path.toFile();
            opFolders.add(aFile);
        }
        return FileVisitResult.CONTINUE;
    }
}



private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {                                           

    JFileChooser chooser = jFileChooser1;
    chooser.setCurrentDirectory(new java.io.File("O:\Prod\Clients"));
    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    chooser.setAcceptAllFileFilterUsed(false);
    int returnVal = chooser.showOpenDialog(this);

    if (returnVal == chooser.APPROVE_OPTION) {
        File file = chooser.getSelectedFile();
        try {
            jTextArea1.setText(null);
            opFolders = new ArrayList<>();

            final Path baseDir = Paths.get(file.getAbsolutePath());
            final List<Path> dirList = new ArrayList<>();
            dirList.add(baseDir);

            final FileVisitor<Path> visitor = new DirectoryCollectorVisitor(dirList);
            Files.walkFileTree(baseDir, visitor);
            if(opFolders.isEmpty()){
                System.err.println("EMPTY");
            }
            for (File aFile : opFolders) {
                if (!aFile.isDirectory() && !aFile.getName().toLowerCase().endsWith(".db")) {
                    jTextArea1.append(aFile.getAbsolutePath() + "\n");

                }

            }

            jTextArea1.append("...COMPLETE...");
        } catch (Exception ex) {
            System.out.println("Problem accessing directory: " + file.getAbsolutePath());
        }
    } else {
        System.out.println("File access cancelled by user.");
    }

}

@fge 更新代码

不幸的是,您说您仅限于 Java 6。鉴于该要求,无法使用 File API 来做到这一点。 .listFiles() 只能以急切的方式填充目录条目。

好吧,有一种方法...如果您使用类似 Unix 的操作系统,您可以使用 ProcessBuilder 并使用诸如 find -type d -name online 之类的命令从基本目录发出进程:

final File baseDir = ...;
final ProcessBuilder pb = new ProcessBuilder(
    "find", "-type", "d", "-name", "online"
);
pb.directory(baseDir);

final Process p = pb.start();
// use the Process' InputStream

如果您使用 Java 7+,您的时间会更轻松;编程 FileVisitor 收集到列表中:

public final class DirectoryCollectorVisitor
    extends SimpleFileVisitor<Path>
{
    private final List<Path> list;

    public DirectoryCollectorVisitor(final List<Path> list)
    {
        this.list = list;
    }

    @Override
    public FileVisitResult previsitDirectory(final Path path, final BasicFileAttributes attrs)
    {
        if (path.getFileName().toString().equals("online"))
            list.add(path);
        return FileVisitResult.CONTINUE;
    }
}

// ...

final Path baseDir = Paths.get(...);
final List<Path> dirList = new ArrayList<>();
final FileVisitor<Path> visitor = new DirectoryCollectorVisitor(list);
Files.walkFileTree(baseDir, visitor);
// dirList is not filled with the entries

有了Java8,就更简单了:

private static final BiPredicate<Path, BasicFileAttributes> ONLINE_DIRS 
    = (path, attrs) -> attrs.isDirectory() 
    && path.getFileName().toString().equals("online");

// ...

final Path baseDir = Paths.get(...);
final List<Path> dirList;

try (
    final Stream<Path> stream = Files.find(baseDir, Integer.MAX_VALUE,
        ONLINE_DIRS);
) {
    dirList = stream.collect(Collectors.toList());
}