【JAVA】遍历打印目录结构

时间:2022-04-04 12:32:36

给定一个目录,打印出该目录包含的目录或者文件的结构来,文件和其父目录之间通过缩进来表示父子关系。

比如:

0 Test$
--1 src$
----2 TravelDir.java
----2 pms$

0 Test$

--1 src$

----2 TravelDir.java

----2 pms$

--1 bin$

表示Test目录下有两个目录:src和bin,src目录里有一个文件TravelDir.java和一个目录pms。(目录名字后面带$,文件不带)


其实遍历打印目录结构,就是对目录这个”树结构“进行遍历,按照上述结构的话,应该是采用深度优先遍历。


为了完成对特定文件名字的筛选,首先定义一个文件名字过滤接口:(策略模式?O(∩_∩)O)

 

【JAVA】遍历打印目录结构【JAVA】遍历打印目录结构FileNameFilter
1 interface FileNameFilter{
2 boolean accept(String filename);
3 }

1)采用递归实现

【JAVA】遍历打印目录结构【JAVA】遍历打印目录结构代码
 1  /*
 2       * 参数:root:要遍历的文件,
 3           *spanToLeft:距离左边的空白或者分隔符数目,
 4           *spanChar:空白字符, 
 5           *filter:根据条件选择文件
 6       * 
 7        */
 8       private   void  travel(File root,  int  spanToLeft,  char  spanChar,
 9              FileNameFilter filter) {
10          spanToLeft  +=   4 ;
11           if  (root.isFile()) {
12              String name  =  root.getName();
13               if  (filter.accept(name)) {
14                   for  ( int  k  =   0 ; k  <  spanToLeft; k ++ ) {
15                      strDir.append(spanChar);
16                  }
17                  strDir.append(root.getName()  +   " \r\n " );
18                  fileCount ++ ;
19              }
20          }  else   if  (root.isDirectory()) {
21               for  ( int  k  =   0 ; k  <  spanToLeft; k ++ ) {
22                  strDir.append(spanChar);
23              }
24              strDir.append(root.getName()  +   " $\r\n " );
25              dirCount ++ ;
26              File[] children  =  root.listFiles();
27               if  (children  ==   null )
28                   return ;
29               for  ( int  i  =   0 ; i  <  children.length; i ++ ) {
30                  travel(children[i], spanToLeft, spanChar, filter);
31              }
32          }
33      }
34      
35       public   void  travelDir(File root,  int  spanToLeft,  char  spanChar,
36              FileNameFilter filter){
37           if  (root  ==   null )
38               return ;
39           if  ( ! root.exists()) {
40              System.err.println( " file  "   +  root.getName()  +   "  does not exist! " );
41               return ;
42          }
43          travel(root, spanToLeft, spanChar, filter);
44          

45     } 

2)采用非递归实现(用堆栈)

为了保存每个文件的层次信息,定义一个类,保存文件名和层次信息
【JAVA】遍历打印目录结构【JAVA】遍历打印目录结构FileDesc
1  class  FileDesc {
2       public  String filename;
3       public   int  fileindex;
4 
5       public  FileDesc(String name,  int  index) {
6          filename  =  name;
7          fileindex  =  index;
8      }

9 } 

非递归代码:

【JAVA】遍历打印目录结构【JAVA】遍历打印目录结构非递归代码
 1  public  ArrayList < FileDesc >  travelWithStack(File root, FileNameFilter filter) {
 2          ArrayList < FileDesc >  res  =   new  ArrayList < FileDesc > ();
 3           if  (root  ==   null )
 4               return  res;
 5          Stack < File >  stack  =   new  Stack < File > ();
 6          Stack < Integer >  stack1  =   new  Stack < Integer > ();
 7          stack.push(root);
 8          stack1.add( 0 );
 9           while  ( ! stack.empty()) {
10              File file  =  stack.pop();
11               int  iii  =  stack1.pop();
12               if  (file.isDirectory()) {
13                  FileDesc desc  =   new  FileDesc(file.getName()  +   " $ " , iii);
14                  res.add(desc);
15                  dirCount ++ ;
16                  File[] children  =  file.listFiles();
17                   if  (children  ==   null )
18                       continue ;
19                   for  ( int  i  =   0 ; i  <  children.length; i ++ ) {
20                      stack.push(children[i]);
21                      stack1.push(iii  +   1 );
22                  }
23              }  else   if  (file.isFile()) {
24                  String filename  =  file.getName();
25                   if  (filter.accept(filename)) {
26                      FileDesc desc  =   new  FileDesc(filename, iii);
27                      res.add(desc);
28                      fileCount ++ ;
29                  }
30              }
31          }
32           return  res;

33     } 

当初学数据结构的时候,学到树遍历那一章,感觉用递归实现遍历,无论是深度优先还是广度优先(注:转成非递归,深度优先用堆栈,广度优先用队列),代码都比较简单而且容易理解。那时候听说非递归实现很难实现,因此连敢看都没敢看,其实那本书也提供了伪代码。但当时感觉还是不怎么明白,也没怎么仔细看。所以一直以来觉得递归转非递归很难,而且也没怎么实际写过代码。前段时间去参加一个单位的笔试题,里面就有一道题要求用非递归实现二叉树的先序遍历,呵呵,说实话,以前还真没怎么写过,都是用递归。于是在考场时试着写了一下,没想到仔细理了一下思路,很快就写出来了,其实没想象中那么难。最近也在研究了一下算法,感觉还是很有意思的,以前总觉得算法很深奥,其实现在想想,没那么高深,关键不能只是在想,要亲自去试试。

ps:也许很多事情没我们想象的那么复杂,亲自去尝试一下,你不去尝试怎么知道自己不行呢。。。
 
其实写这个程序主要有一个目的,就是想统计一下我电脑里的音乐文件夹下面的音乐文件。以下是我用程序输出的结果(直接输出到文件里):
对音乐感兴趣的朋友可以下来看看,丰富你的音乐库,哈哈