`
mo^xu
  • 浏览: 5941 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

遍历深层次的树状结构 查找硬盘中的 “java.exe”

阅读更多
遍历深层次的树状结构 查找硬盘中的 “java.exe”


原文:http://www.yi-dao.com/works/model/sample/findFiles.htm
遍历深层次的树状结构。这里的例子是查找所有本地硬盘中的“java.exe”文件。
当向一个深层的目录寻找特定的文件时,很容易想到通过不断地迭代来遍历。

import java.io.File;

public class FileSearchTool {
  public static void main(String[] args) {
    String toFind = "java.exe";
    File[] roots = File.listRoots();
    for (int i = 0; i < roots.length; i++) {
      searchList(roots[i], toFind);
    }
  }

  public static void searchList(File file, String toFind) {
    File[] files = file.listFiles();
    if (files != null) {
      for (int i = 0; i < files.length; i++) {
        if (files[i].isDirectory()) {
          searchList(file, toFind);
        }
        else if (files[i].getName().equals(toFind)) {
          System.out.println(files[i].getAbsolutePath());
        }
      }
    }
  }
}

上面的代码表面上看好象可以完成任务,可上面的方法却是无效的。上面忽略了目录的深度与广度,在递归的过程中不断地分配资源(File[] files = file.listFiles();),而只有当更深层的递归结束时才能结束当前的工作并释放这些资源,这样极容易导致堆栈溢出和 JVM 停止工作。
为了解决这样的问题,应该尽量避免使用递归。不用递归也不分配大量资源的方法才是有效的方法。

下面是不用递归时查找硬盘中的 "java.exe" 的程序。分析这个过程的状态机请见:http://www.yi-dao.com/works/model/sample/findFiles.ydm 下载这个文档,使用“易道模型”打开,易道模型下载:http://www.sharebank.com.cn/soft/soft_view.php?id=11135
-------------------------------------------------------

public class Test{
  public static void main(String[] args) {
    File[] roots = File.listRoots();
    String nameToFind = "java.exe";
    for (int i = 0; i < roots.length; i++) {
      File[] files = findFiles(roots[i], nameToFind);
      for (int j = 0; j < files.length; j++) {
        System.out.println(files[j].getAbsolutePath());
      }
    }
  }

  public static File[] findFiles(File dir, String nameToFind) {
    Stack curPath = new Stack();
    curPath.push(dir);
    return findFiles(curPath, nameToFind);
  }

  public static final int FIND_SUB = 0; // 找子节点
  public static final int FIND_SIB = 1; // 找同级节点
  public static final int FIND_END = 2; // 结束
  public static File[] findFiles(Stack curPath, String nameToFind) {
    /** 只检测目录 */
    class MyDirFilter
        implements FileFilter {
      public boolean accept(File pathname) {
        return (pathname != null) && pathname.isDirectory();
      }
    }

    /** 只检测文件名相同 */
    class MyFileFilter
        implements FileFilter {
      String toFind;
      MyFileFilter(String toFind) {
        this.toFind = toFind;
      }

      public boolean accept(File pathname) {
        return (pathname != null) && pathname.isFile()
            && toFind.equalsIgnoreCase(pathname.getName());
      }
    }

    MyFileFilter fileFilter = new MyFileFilter(nameToFind);
    MyDirFilter dirFilter = new MyDirFilter();
    int state = FIND_SUB; // 开始
    LinkedHashSet found = new LinkedHashSet();
    while (state != FIND_END) {
      File dir = (File) curPath.pop(); // 当前目录
      // System.out.println(dir.getAbsolutePath());
      if (state == FIND_SUB) { // 查找子节点
        File[] subDirs = dir.listFiles(dirFilter);
        if (subDirs == null || subDirs.length == 0) { // 没有子节点
          curPath.push(dir);
          state = FIND_SIB; // 下一次需要找同级节点
        }
        else {
          curPath.push(dir);
          curPath.push(subDirs[0]);
          state = FIND_SUB;
        }
      }
      else if (state == FIND_SIB) { // 查找同级节点
        File[] files = dir.listFiles(fileFilter);
        if (files != null) {
          for (int i = 0; i < files.length; i++) {
            found.add(files[i]);
          }
        }

        if (curPath.isEmpty()) {
          state = FIND_END; // 已经没有可以找的了,需要退出查找过程
        }
        else {
          File parentDir = (File) curPath.peek();
          File[] sibDirs = parentDir.listFiles(dirFilter);
          for (int i = 0; i < sibDirs.length; i++) {
            if (dir.equals(sibDirs[i])) { // 找到了当前的位置
              if (i + 1 < sibDirs.length) { // 存在下一个同级节点
                curPath.push(sibDirs[i + 1]);
                state = FIND_SUB; // 需要查找子节点
              }
              else { // 这就是最后一个同级节点
                state = FIND_SIB;
              }
              break;
            }
          }
        }
      }
    }
    return (File[]) found.toArray(new File[found.size()]);
  }
}

上面的方法在整个文件目录的遍历过程中只使用了一个 LinkedHashSet 来记录当前的路径信息,并没有在向更深层次遍历时大量开销过多的资源,所以JVM是可以承受的。这样的方法才有效。

分享到:
评论

相关推荐

    46.java数组遍历1.zip

    46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip46.java数组遍历1.zip...

    php遍历目录生成树状结构

    一个类,可以遍历一个目录,将该目录下所有文件以及子目录及其文件都遍历,生成一个层次分明的数组,还可以将遍历的结果生成一个树状的字符串,直接echo到浏览器。 |-|a.txt |-|b.txt |-|c目录 |---|d.txt |---|c1...

    php 遍历目录生成树状结构

    一个类,可以遍历一个目录,将该目录下所有文件以及子目录及其文件都遍历,生成一个层次分明的数组,还可以将遍历的结果生成一个树状的字符串,直接echo到浏览器。 |-|a.txt |-|b.txt |-|c目录 |---|d.txt |---|c1...

    java遍历文件目录生成树结构txt文件

    在Java编程中,遍历文件目录并生成树结构的文本文件是一个常见的任务,尤其是在处理大量文件数据时。这个任务可以通过使用Java的`java.io.File`类及其相关API来实现。`Dir.class`和`Dir.java`是这次操作的核心文件,...

    java 全硬盘文件遍历

    java全硬盘文件遍历,添加到树中,在面板中显示,没有事件处理

    遍历查找硬盘中所有文件夹及文件,包括隐藏文件

    总之,遍历查找硬盘中的所有文件和文件夹是一项基础但重要的任务,涉及文件系统结构、遍历算法和可能的权限控制。通过各种编程语言和工具,我们可以有效地实现这一功能,包括查找隐藏文件,以满足不同场景的需求。

    Java实现遍历、排序、查找算法及简要说明.docx

    在本文档中,我们主要探讨了Java中关于遍历、排序和查找算法的实现和简要说明。首先,我们详细介绍了二叉树的遍历算法,包括四种主要的遍历方式:先序遍历、中序遍历、后序遍历和层次遍历。 1. **遍历算法**: - *...

    java遍历文件树形结构输出

    3. **File类**: Java中的`File`类提供了一个抽象表示文件和目录路径名的平台独立方式。 #### 二、代码解析 根据题目提供的代码片段,我们可以看到这是一个简单的Java程序,用于遍历指定路径下的所有文件及子目录,...

    遍历多级树状json获得父子节点值

    在IT行业中,处理数据结构是常见的任务之一,特别是在面对复杂的数据结构如树状JSON时。树状JSON结构常用于表示层级关系,例如组织结构、文件系统或者导航菜单等。本篇将详细介绍如何遍历多级嵌套或树状的JSON结构,...

    java中遍历某个目录下的所有文件及文件夹中的文件

    ### Java中遍历某个目录下的所有文件及文件夹中的文件 在Java开发中,经常会遇到需要遍历指定目录及其子目录下所有文件的情况。本文将详细介绍如何使用Java标准库中的`java.io.File`类来实现这一功能。我们将通过一...

    C语言编程实现10个数据结构课程设计实例-二叉树建立遍历冒泡排序快速排序等.zip

    二叉树层次遍历.c 二叉树非递归遍历.c 二叉树建立.c 快速排序.c 括号匹配.c 冒泡排序.c 直接插入排序.c 直接选择排序.c 10个数据结构课程设计例子 查找.c 二叉排序树.c 二叉树层次遍历.c 二叉树非递归遍历.c 二叉树...

    java.util.ConcurrentModificationException 异常问题详解1

    Iterator 是 Java 集合框架中的一个接口,用于遍历集合中的元素。它提供了 hasNext()、next() 和 remove() 三个方法,分别用于判断是否还有下一个元素、获取下一个元素和删除当前元素。 下面是一个抛出 ...

    文件遍历Everything-1.4.1.988.x86-Setup.exe

    文件遍历Everything-1.4.1.988.x86-Setup.exe

    Java 遍历文件夹内文件

    在Java中,有时我们会使用第三方库,如Apache Commons IO或Guava,来简化文件操作,这些库提供了更多的功能和便利。 在提供的压缩包文件中,有两个名为`FileSystem.java`和`FileSystem1.java`的文件。通常,这些...

    java深度优先遍历

    在Java中,我们可以利用递归或栈数据结构来实现这一算法。DFS的主要思想是从根节点开始,沿着某一条路径一直深入到不能再深入为止,然后回溯到上一个节点,再选择另一条路径继续深入。 1. **DFS的基本概念**: ...

    按层次遍历二叉树,数据结构

    按层次遍历二叉树是一种常见的树遍历算法,顾名思义,即按照树的层次结构对树中的结点进行遍历。这种遍历方式的特点是,先访问当前层次的所有结点,然后再访问下一层次的结点,以此类推,直到遍历整个树。这种遍历...

    遍历二叉树(java实现)

    在Java中,可以使用以下递归方式实现: ```java public void preOrderTraversal(TreeNode node) { if (node != null) { System.out.println(node.value); // 访问当前节点 preOrderTraversal(node.left); // ...

    二叉树层次遍历.rar

    数据结构课程设计实例二叉树层次遍历 数据结构课程设计实例二叉树层次遍历 数据结构课程设计实例二叉树层次遍历 数据结构课程设计实例二叉树层次遍历 数据结构课程设计实例二叉树层次遍历 数据结构课程设计实例...

    java树的前中后序遍历

    用递归和堆栈两种方法对树分别进行前中后序的遍历

Global site tag (gtag.js) - Google Analytics