1 public void BFS(DirectoryInfo dir, ref long nfile, ref long ndir)
2 {
3 try
4 {
5 IEnumerable<string> ieDir = Directory.EnumerateDirectories(dir.FullName);
6
7 IEnumerator<string> iDir = ieDir.GetEnumerator();
8
9 do
10 {
11 if (iDir.Current != null)
12 {
13 Console.WriteLine(iDir.Current.ToString());
14 ndir++;
15
16 try
17 {
18 IEnumerable<string> ieFile = Directory.EnumerateFiles(iDir.Current.ToString());
19
20 IEnumerator<string> iFile = ieFile.GetEnumerator();
21 do
22 {
23 if (iFile.Current != null)
24 {
25 Console.WriteLine(iFile.Current.ToString());
26 nfile++;
27 }
28
29 }
30 while (iFile.MoveNext());
31 }
32 catch
33 {
34
35 }
36
37 BFS(new DirectoryInfo(iDir.Current.ToString()), ref nfile, ref ndir);
38
39 }
40
41
42 }
43 while (iDir.MoveNext());
44 }
45 catch
46 {
47
48 }
49
50 }
1 public void BFS2(DirectoryInfo dir, ref long nFile, ref long nDir)
2 {
3 try
4 {
5 if (dir.Exists)
6 {
7 Console.WriteLine(dir.FullName);
8 nDir++;
9
10 try
11 {
12 FileInfo[] arrFile = dir.GetFiles();
13
14 foreach (FileInfo fiNode in arrFile)
15 {
16 if (fiNode.Exists)
17 {
18 Console.WriteLine(fiNode.FullName);
19 nFile++;
20 }
21
22 }
23 }
24 catch
25 {
26
27 }
28
29 }
30
31 DirectoryInfo[] arrDir = dir.GetDirectories();
32 foreach (DirectoryInfo node in arrDir)
33 {
34 BFS2(node, ref nFile, ref nDir);
35 }
36 }
37 catch
38 {
39
40 }
41
42 }
1 /// <summary>
2 /// 广度优先遍历 : 用队列
3 /// </summary>
4 /// <param name="dir"></param>
5 public string BFS(DirectoryInfo dir)
6 {
7 long nFileCount = 0;
8 long nDirCount = 0;
9
10 //文件队列
11 Queue<DirectoryInfo> dirList = new Queue<DirectoryInfo>();
12 dirList.Enqueue(dir);
13
14 //是否包含有子文件夹
15 bool bIsHasChildDir = true;
16
17 while (bIsHasChildDir)
18 {
19
20 //1. 文件夹出队
21 //取文件信息
22 //取子文件夹信息
23 //输出出队文件夹信息
24
25 DirectoryInfo WriteDir = dirList.Dequeue();
26
27 Console.WriteLine(WriteDir.FullName);
28 nDirCount++;
29
30 try
31 {
32 //2.当前目录文件扫描(广度遍历)
33 FileInfo[] fiList = WriteDir.GetFiles();
34
35 foreach (FileInfo node in fiList)
36 {
37 if (node.Exists)
38 {
39 Console.WriteLine(node.FullName);
40 nFileCount++;
41 }
42 }
43 }
44 catch
45 {
46
47 }
48
49 try
50 {
51 //3.子文件夹入队
52 DirectoryInfo[] diList = WriteDir.GetDirectories();
53
54 foreach (DirectoryInfo node in diList)
55 {
56 if (node.Exists)
57 {
58 //入队,同时开始访问文件夹
59 dirList.Enqueue(node);
60 }
61 }
62 }
63 catch { }
64
65 //队列中没有文件夹可访问
66 if (dirList.Count == 0)
67 {
68 bIsHasChildDir = false;
69 }
70
71 }
72
73 return string.Format("FileCount:{0}, DirCount:{1}", nFileCount, nDirCount);
74
75 }
1 /// <summary>
2 /// 深度优先遍历 : 用栈 =二叉树的前序遍历 (传统深度遍历)
3 /// </summary>
4 /// <param name="dir"></param>
5 public string DFS(DirectoryInfo dir)
6 {
7 long nFileCount = 0;
8 long nDirCount = 0;
9
10 //1.把root 压入 栈中
11 Stack<DirectoryInfo> dirStack = new Stack<DirectoryInfo>();
12 dirStack.Push(dir);
13
14 DirectoryInfo parent = null;
15 while (dirStack.Count != 0)
16 {
17 //读顶栈
18 DirectoryInfo current = dirStack.Pop();
19
20 //输出当前目录
21 Console.WriteLine(current.FullName);
22 nDirCount++;
23 try
24 {
25
26 FileInfo[] fiList = current.GetFiles();
27
28 foreach (FileInfo node in fiList)
29 {
30 Console.WriteLine(node.FullName);
31 nFileCount++;
32 }
33
34 }
35 catch
36 {
37
38 }
39
40
41 //
42 try
43 {
44
45 DirectoryInfo[] dirList = current.GetDirectories();
46
47 foreach (DirectoryInfo node in dirList)
48 {
49 dirStack.Push(node);
50 }
51 }
52 catch
53 {
54
55 }
56
57 }
58
59 return string.Format("FileCount:{0}, DirCount:{1}", nFileCount, nDirCount);
60 }
实现
1 class Program
2 {
3
4 public static string GetTimeSpanFormatText(DateTime dateStart)
5 {
6 string strSpan = "span:{0}d{1}h{2}m{3}s{4}ms";
7 TimeSpan tsSpan = DateTime.Now - dateStart;
8 string strReturn = string.Format(strSpan, tsSpan.Days, tsSpan.Hours, tsSpan.Minutes, tsSpan.Seconds, tsSpan.Milliseconds);
9 return strReturn;
10 }
11
12 static void Main(string[] args)
13 {
14 DirectoryInfo root = new DirectoryInfo("C:\\");
15
16 Recursion lsFile = new Recursion();
17 DateTime start = DateTime.Now;
18 Console.WriteLine(start.ToLongTimeString());
19 long nFileCount1 = 0;
20 long nDirCount1 = 0;
21 lsFile.BFS(root, ref nFileCount1, ref nDirCount1);
22 Console.WriteLine(GetTimeSpanFormatText(start));
23 Console.WriteLine(string.Format("FileCount:{0}, DirCount:{1}", nFileCount1, nDirCount1));
24 Console.WriteLine("OK");
25 Console.ReadLine();
26
27 Recursion lsFile2 = new Recursion();
28 DateTime start2 = DateTime.Now;
29 long nFileCount = 0;
30 long nDirCount = 0;
31 lsFile2.BFS2(root, ref nFileCount, ref nDirCount);
32 Console.WriteLine(GetTimeSpanFormatText(start2));
33 Console.WriteLine(string.Format("FileCount:{0}, DirCount:{1}", nFileCount, nDirCount));
34 Console.WriteLine("OK");
35
36 Console.ReadLine();
37
38 UnRecursion btree = new UnRecursion();
39 DateTime start3 = DateTime.Now;
40 string strBFS = btree.BFS(root);
41 Console.WriteLine(GetTimeSpanFormatText(start3));
42 Console.WriteLine(strBFS);
43 Console.WriteLine("OK");
44
45 Console.ReadLine();
46
47
48 UnRecursion btree3 = new UnRecursion();
49 DateTime start5 = DateTime.Now;
50 string strResult = btree3.DFS(root);
51 Console.WriteLine(GetTimeSpanFormatText(start5));
52 Console.WriteLine(strResult);
53 Console.WriteLine("OK");
54
55 Console.ReadLine();
56
57 }
58
59
60 }
结果对比
0:2:41:070 C:\ 递归1 file 138917 dir 28678
0:2:52:209 C:\ 递归2 file 138919 dir 28673
0:2:53:113 C:\ BFS file 138915 dir 28673
0:4:57:523 C:\ DFS file 138915 dir 28673
结论
[单线程的情况下]
对于文件系统树的遍历来说使用广度优先要比深度优先要更好些,理由是:
1、DFS每次遇到目录则立即深入搜索,因此需要保存大量句柄,而BFS则避免用太多句柄;
2、同一个目录下的文件在硬盘的物理结构上更邻近些,所以BFS更快